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雖然是一個靜態作用域語言,但變數名查詢是動態發生的,直到在程式執行時,才會發現作用域方面的問題。