python基礎篇11-函數
函數
函數一詞來源於數學,但編程中的「函數」概念,與數學中的函數是有很大不同的,具體區別,我們後面會講,編程中的函數在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子過程或子程序),在Pascal中叫做procedure(過程)和function,在C中只有function,在Java裏面叫做method。函數能提高應用的模塊性,和代碼的重復利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。
定義: 函數是指將一組語句的集合通過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名即可
特性:
1.代碼重用
2.保持一致性
3.可擴展性
函數的創建
1.格式
Python 定義函數使用 def 關鍵字,一般格式如下:
1 #def 函數名(參數列表): 2 # 函數體 3 4 def hello(): 5 print(‘hello‘) 6 7 hello()#調用
2.函數的命名規則
- 函數名必須以下劃線或字母開頭,可以包含任意字母、數字或下劃線的組合。不能使用任何的標點符號;
- 函數名是區分大小寫的。
- 函數名不能是保留字。
3.形參和實參
形參:形式參數,不是實際存在,是虛擬變量。在定義函數和函數體的時候使用形參,目的是在函數調用時接收實參(實參個數,類型應與實參一一對應)
實參:實際參數,調用函數時傳給函數的參數,可以是常量,變量,表達式,函數,傳給形參
區別:形參是虛擬的,不占用內存空間,.形參變量只有在被調用時才分配內存單元,實參是一個變量,占用內存空間,數據傳送單向,實參傳給形參,不能形參傳給實參。
1 import time 2 times=time.strftime(‘%Y--%m--%d‘) 3 def f(time): 4 print(‘Now time is : %s‘%times) 5 f(times)
4.實例
現在我們就用一個例子來說明函數的三個特性:
1 def action1(n): 2 print函數的特性展示(‘starting action1...‘) 3 4 with open(‘日誌記錄‘,‘a‘) as f: 5 f.write(‘end action%s\n‘%n) 6 7 def action2(n): 8 print (‘starting action2...‘) 9 10 with open(‘日誌記錄‘,‘a‘) as f: 11 f.write(‘end action%s\n‘%n) 12 13 def action3(n): 14 print (‘starting action3...‘) 15 16 with open(‘日誌記錄‘,‘a‘) as f: 17 f.write(‘end action%s\n‘%n) 18 19 action1(1) 20 action2(2) 21 action3(3) 22 23 24 ##***************代碼重用 25 26 def logger(n): 27 with open(‘日誌記錄‘,‘a‘) as f: 28 f.write(‘end action%s\n‘%n) 29 30 def action1(): 31 print (‘starting action1...‘) 32 logger(1) 33 34 35 def action2(): 36 print (‘starting action2...‘) 37 logger(2) 38 39 40 def action3(): 41 print (‘starting action3...‘) 42 logger(3) 43 44 45 action1() 46 action2() 47 action3() 48 49 ##***************可擴展和保持一致 50 ##為日誌加上時間 51 import time 52 53 def logger(n): 54 time_format=‘%Y-%m-%d %X‘ 55 time_current=time.strftime(time_format) 56 57 with open(‘日誌記錄‘,‘a‘) as f: 58 f.write(‘%s end action%s\n‘%(time_current,n)) 59 60 def action1(): 61 print (‘starting action1...‘) 62 logger(1) 63 64 65 def action2(): 66 print (‘starting action2...‘) 67 logger(2) 68 69 70 def action3(): 71 print (‘starting action3...‘) 72 logger(3) 73 74 action1() 75 action2() 76 action3()
函數的參數
- 必備參數
- 關鍵字參數
- 默認參數
- 不定長參數
1.必須參數
必需參數須以正確的順序傳入函數。調用時的數量必須和聲明時的一樣。
1 def f(name,age): 2 3 print(‘I am %s,I am %d‘%(name,age)) 4 5 f(‘alex‘,18) 6 f(‘alvin‘,16)
2.關鍵字參數
關鍵字參數和函數調用關系緊密,函數調用使用關鍵字參數來確定傳入的參數值。使用關鍵字參數允許函數調用時參數的順序與聲明時不一致,因為 Python 解釋器能夠用參數名匹配參數值。
1 def f(name,age): 2 3 print(‘I am %s,I am %d‘%(name,age)) 4 5 # f(16,‘alvin‘) #報錯 6 f(age=16,name=‘alvin‘)
3.默認參數
調用函數時,缺省參數的值如果沒有傳入,則被認為是默認值。下例如果sex沒有被傳入,會打印默認的sex:
1 def print_info(name,age,sex=‘male‘): 2 3 print(‘Name:%s‘%name) 4 print(‘age:%s‘%age) 5 print(‘Sex:%s‘%sex) 6 return 7 8 print_info(‘alex‘,18) 9 print_info(‘鐵錘‘,40,‘female‘)
4.不定長參數
你可能需要一個函數能處理比當初聲明時更多的參數。這些參數叫做不定長參數,和上述2種參數不同,聲明時不會命名。
1 def add(*args): 2 sum=0 3 for v in args: 4 sum+=v 5 #print(args) 輸出(1,4,6,9),即會以元組的形式存放參數 6 return sum 7 8 print(add(1,4,6,9)) 9 print(add(1,4,6,9,5))
加了星號(*)的變量名會存放所有未命名的變量參數。而加(**)的變量名會存放命名的變量參數:
1 def print_info(**kwargs): 2 print(kwargs) #輸出:{‘sex‘: ‘female‘, ‘name‘: ‘alex‘, ‘ability‘: ‘Python‘, ‘age‘: 18, ‘nationality‘: ‘Chinese‘, ‘hobby‘: ‘girl‘}即以字典的方式存放變量 3 for i in kwargs: 4 print(‘%s:%s‘ % (i, kwargs[i])) # 根據參數可以打印任意相關信息了 5 6 return 7 8 9 print_info(name=‘alex‘, age=18, sex=‘female‘, hobby=‘girl‘, nationality=‘Chinese‘, ability=‘Python‘)
位置:
1 def print_info(name,*args,**kwargs):#def print_info(name,**kwargs,*args):報錯 2 3 print(‘Name:%s‘%name) 4 5 print(‘args:‘,args) 6 print(‘kwargs:‘,kwargs) 7 8 return 9 10 print_info(‘alex‘,18,hobby=‘girl‘,nationality=‘Chinese‘,ability=‘Python‘) 11 # print_info(hobby=‘girl‘,‘alex‘,18,nationality=‘Chinese‘,ability=‘Python‘) #報錯 12 #print_info(‘alex‘,hobby=‘girl‘,18,nationality=‘Chinese‘,ability=‘Python‘) #報
註意,還可以這樣傳參:
1 ef f(*args): 2 print(args) 3 4 f(*[1,2,5]) 5 6 def f(**kargs): 7 print(kargs) 8 9 f(**{‘name‘:‘alex‘})
函數的返回值
要想獲取函數的執行結果,就可以用return語句把結果返回。
註意:
- 函數在執行過程中只要遇到return語句,就會停止執行並返回結果,所以也可以理解為 return 語句代表著函數的結束;
- 如果未在函數中指定return,那這個函數的返回值為None;
- return多個對象,解釋器會把這多個對象組裝成一個元組作為一個一個整體結果輸出。
作用域
1.作用域介紹:
python中的作用域分4種情況:
- L:local,局部作用域,即函數中定義的變量;
- E:enclosing,嵌套的父級函數的局部作用域,即包含此函數的上級函數的局部作用域,但不是全局的;
- G:globa,全局變量,就是模塊級別定義的變量;
- B:built-in,系統固定模塊裏面的變量,比如int, bytearray等。 搜索變量的優先級順序依次是:作用域局部>外層作用域>當前模塊中的全局>python內置作用域,也就是LEGB。
1 x = int(2.9) # int built-in 2 3 g_count = 0 # global 4 def outer(): 5 o_count = 1 # enclosing 6 def inner(): 7 i_count = 2 # local 8 print(o_count) #輸出1 9 #print(i_count) 找不到 10 inner() 11 outer() 12 13 # print(o_count) #找不到
2.作用域的產生:
在Python中,只有模塊(module),類(class)以及函數(def、lambda)才會引入新的作用域,其它的代碼塊(如if、try、for等)是不會引入新的作用域的,如下代碼:
1 if 2>1: 2 x = 1 3 print(x) # 1
這個是沒有問題的,if並沒有引入一個新的作用域,x仍處在當前作用域中,後面代碼可以使用。
1 def test(): 2 x = 2 3 print(x) # NameError: name ‘x2‘ is not defined
def、class、lambda是可以引入新作用域的。print(x)中的x不處於當前作用域中。
3.變量的修改:
1 ################# 2 x=6 3 def f2(): 4 print(x) 5 x=5 6 f2() 7 8 # 錯誤的原因在於print(x)時,解釋器會在局部作用域找,會找到x=5(函數已經加載到內存),但x使用在聲明前了,所以報錯: 9 # local variable ‘x‘ referenced before assignment. 10 #同理 11 x=6 12 def f2(): 13 x+=1 #local variable ‘x‘ referenced before assignment. 14 f2()
4.global關鍵字:
當內部作用域想修改外部作用域的變量時,就要用到global和nonlocal關鍵字了,當修改的變量是在全局作用域(global作用域)上的,就要使用global先聲明一下,代碼如下:
1 count = 10 2 def outer(): 3 global count 4 print(count) #正常情況下,count位於global作用域上,在內部作用域裏可以查看但不能修改,如果要修改就需要使用global關鍵字了 5 count = 100 #修改global作用域上的變量 6 print(count) 7 outer() 8 #10 9 #100
5.nonlocal關鍵字:
global關鍵字聲明的變量必須在全局作用域上,不能位於嵌套作用域上,當要修改嵌套作用域(enclosing作用域,外層非全局作用域)中的變量時就需要nonlocal關鍵字:
1 def outer(): 2 count = 10 3 def inner(): 4 nonlocal count 5 count = 20 6 print(count) 7 inner() 8 print(count) 9 outer() 10 #20 11 #20
6.總結:
(1)變量查找順序:LEGB,作用域局部>外層作用域>當前模塊中的全局>python內置作用域;
(2)只有模塊、類、及函數才能引入新作用域。其它的代碼塊(如if、try、for等)是不會引入新的作用域的;
(3)對於一個變量,內部作用域聲明了就會覆蓋外部變量。不聲明直接使用,就會使用外部作用域的變量;
(4)內部作用域要修改外部作用域變量的值時,全局變量要使用global關鍵字,嵌套作用域變量要使用nonlocal關鍵字。nonlocal是python3新增的關鍵字,有了這個 關鍵字,就能完美的實現閉包了。
python基礎篇11-函數