1. 程式人生 > >Python學習日記-14-函式

Python學習日記-14-函式

def f():
    print('ok')

f()   #  ok
def add(x,y):
    print(x + y)

add(3,5)      # 8
def print_info(name, age, sex='male'):        # 預設引數一定要跟在其他引數後面
    print('Name: %s'% name)
    print('Age: %d' % age)
    print('Sex: %s' % sex)


print_info('kkk',18)                           # 必需引數
print_info(name='ooo', age=18)                 # 關鍵字引數
print_info(name='ppp', age=18, sex='famale')   # 預設引數
def add(*args):        # 不定長引數
    print(args)
    Sum = 0
    for i in args:     # 將引數做成元組
        Sum += i
    print(Sum)

add(2, 6)
def print_info(p='ll', *args, **kwargs):       # 將引數做成一個字典
    print(p)
    print(args)                        # ('ooo', 'ee', 25)
    print(kwargs)                      # {'name': 'zhr', 'age': 18, 'sex': 'male'}

    for i in kwargs:
        print(i, kwargs[i])

print_info('ooo', 'ee', 25, name='zhr', age=18, sex='male')
# 順序:關鍵字引數  ->  預設引數  ->   *args  ->   **kwargs
def add(*args):        # 不定長引數
    Sum = 0
    for i in args:     # 將引數做成元組
        Sum += i
    return Sum         # 結束函式,返回值
                       # 函式裡如果沒有return,會預設返回None

print(add(3, 6))  # 9
def foo():
    return 1, 'oo', 89   # ruturn 多個物件會把多個物件封裝成一個元組返回

print(foo())     # (1, 'oo', 89)

作用域


L(local)區域性作用域

區域性變數:包含在def關鍵字定義的語句塊中,即在函式中定義的變數。每當函式被呼叫時都會建立一個新的區域性作用域。Python中也有遞迴,即自己呼叫自己,每次呼叫都會建立一個新的區域性名稱空間。在函式內部的變數宣告,除非特別的宣告為全域性變數,否則均預設為區域性變數。有些情況需要在函式內部定義全域性變數,這時可以使用global關鍵字來宣告變數的作用域為全域性。區域性變數域就像一個 棧,僅僅是暫時的存在,依賴建立該區域性作用域的函式是否處於活動的狀態。所以,一般建議儘量少定義全域性變數,因為全域性變數在模組檔案執行的過程中會一直存在,佔用記憶體空間。注意:如果需要在函式內部對全域性變數賦值,需要在函式內部通過global語句宣告該變數為全域性變數。

E(enclosing)巢狀作用域

E也包含在def關鍵字中,E和L是相對的,E相對於更上層的函式而言也是L。與L的區別在於,對一個函式而言,L是定義在此函式內部的區域性作用域,而E是定義在此函式的上一層父級函式的區域性作用域。主要是為了實現Python的閉包,而增加的實現。

G(global)全域性作用域

即在模組層次中定義的變數,每一個模組都是一個全域性作用域。也就是說,在模組檔案頂層宣告的變數具有全域性作用域,從外部開來,模組的全域性變數就是一個模組物件的屬性。注意:全域性作用域的作用範圍僅限於單個模組檔案內。

B(built-in)內建作用域

系統內固定模組裡定義的變數,如預定義在builtin 模組內的變數。

def func():                # 在作用域中定義的變數,一般只在作用域中有效。
    variable = 100
    print (variable)

print (variable)        #NameError: name 'variable' is not defined
if True:                     # 需要注意的是:在if-elif-else、for-else、while、try-except\try-finally
                             # 等關鍵字的語句塊中並不會產成作用域
    variable = 100
    print (variable)
print ("******")
print (variable)
def func():
    variable = 300
    print (variable)

variable = 100
func()            #300
print (variable)  #100
variable = 300
def test_scopt():
    print (variable)    #variable是test_scopt()的區域性變數,但是在列印時並沒有繫結記憶體物件。
    variable = 200      #因為這裡,所以variable就變為了區域性變數
test_scopt()
print (variable)

上面的例子會報出錯誤,因為在執行程式時的預編譯能夠在test_scopt()中找到區域性變數variable(對variable進行了賦值)。在區域性作用域找到了變數名,所以不會升級到巢狀作用域去尋找。但是在使用print語句將變數variable列印時,區域性變數variable並有沒繫結到一個記憶體物件(沒有定義和初始化,即沒有賦值)。本質上還是Python呼叫變數時遵循的LEGB法則和Python解析器的編譯原理,決定了這個錯誤的發生。所以,在呼叫一個變數之前,需要為該變數賦值(繫結一個記憶體物件)。注意:為什麼在這個例子中觸發的錯誤是UnboundLocalError而不是NameError:name ‘variable’ is not defined。因為變數variable不在全域性作用域。Python中的模組程式碼在執行之前,並不會經過預編譯,但是模組內的函式體程式碼在執行前會經過預編譯,因此不管變數名的繫結發生在作用域的那個位置,都能被編譯器知道。Python雖然是一個靜態作用域語言,但變數名查詢是動態發生的,直到在程式執行時,才會發現作用域方面的問題。