国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Python函數(shù)小結(1)--參數(shù)類型(*,**的區(qū)別),閉包

2019-11-14 17:18:36
字體:
來源:轉載
供稿:網(wǎng)友

剛開始學習python,python相對于java確實要簡潔易用得多。內存回收類似hotspot的可達性分析, 不可變對象也如同java得Integer類型,with函數(shù)類似新版本C++的特性,總體來說理解起來比較輕松。只是函數(shù)部分參數(shù)的"*"與"**",閉包等問題,著實令人迷糊了一把,弄清概念后寫下此文記錄下來,也希望本文能夠幫助其他初學者。

所以本文是一篇學習筆記,著重于使用的細節(jié)和理解上,首先分別介紹了函數(shù)各種參數(shù)類型在調用和聲明時的區(qū)別,及其在混用時需要注意的一些細節(jié),之后講了閉包相關的內容。如果有不對的地方歡迎指正。

函數(shù)參數(shù)不帶“*”,"*" 與 "**"的區(qū)別

理解這個問題得關鍵在于要分開理解調用和聲明語法中3者得區(qū)別.

函數(shù)調用區(qū)別

1. 不同類型的參數(shù)簡述

#這里先說明python函數(shù)調用得語法為:func(positional_args, keyWord_args, *tuple_grp_nonkw_args, **dict_grp_kw_args)  #為了方便說明,之后用以下函數(shù)進行舉例 def test(a,b,c,d,e):	 PRint a,b,c,d,e

舉個例子來說明這4種調用方式得區(qū)別:

#-------------------------------#positional_args方式>>> test(1,2,3,4,5)1 2 3 4 5#這種調用方式的函數(shù)處理等價于a,b,c,d,e = 1,2,3,4,5print a,b,c,d,e#-------------------------------#keyword_args方式>>> test(a=1,b=3,c=4,d=2,e=1)1 3 4 2 1#這種處理方式得函數(shù)處理等價于a=1b=3c=4d=2e=1print a,b,c,d,e#-------------------------------#*tuple_grp_nonkw_args方式>>> x = 1,2,3,4,5>>> test(*x)1 2 3 4 5#這種方式函數(shù)處理等價于a,b,c,d,e = xprint a,b,c,d,e#特別說明:x也可以為dict類型,x為dick類型時將鍵傳遞給函數(shù)>>> y{'a': 1, 'c': 6, 'b': 2, 'e': 1, 'd': 1}>>> test(*y)a c b e d#---------------------------------#**dict_grp_kw_args方式>>> y{'a': 1, 'c': 6, 'b': 2, 'e': 1, 'd': 1}>>> test(**y)1 2 6 1 1#這種函數(shù)處理方式等價于a = y['a']b = y['b']... #c,d,e不再贅述print a,b,c,d,e

2. 不同類型參數(shù)混用需要注意的一些細節(jié)

  接下來說明不同參數(shù)類型混用的情況,要理解不同參數(shù)混用得語法需要理解以下幾方面內容.

  首先要明白,函數(shù)調用使用參數(shù)類型必須嚴格按照順序,不能隨意調換順序,否則會報錯. 如 (a=1,2,3,4,5)會引發(fā)錯誤,; (*x,2,3)也會被當成非法.

  其次,函數(shù)對不同方式處理的順序也是按照上述的類型順序.因為#keyword_args方式和**dict_grp_kw_args方式對參數(shù)一一指定,所以無所謂順序.所以只需要考慮順序賦值(positional_args)和列表賦值(*tuple_grp_nonkw_args)的順序.因此,可以簡單理解為只有#positional_args方式,#*tuple_grp_nonkw_args方式有邏輯先后順序的.

  最后,參數(shù)是不允許多次賦值的.

  舉個例子說明,順序賦值(positional_args)和列表賦值(*tuple_grp_nonkw_args)的邏輯先后關系:

#只有在順序賦值,列表賦值在結果上存在羅輯先后關系#正確的例子1>>> x = {3,4,5}>>> test(1,2,*x)1 2 3 4 5#正確的例子2>>> test(1,e=2,*x)1 3 4 5 2#錯誤的例子>>> test(1,b=2,*x)Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: test() got multiple values for keyword argument 'b'#正確的例子1,處理等價于a,b = 1,2 #順序參數(shù)c,d,e = x #列表參數(shù)print a,b,c,d,e#正確的例子2,處理等價于a = 1 #順序參數(shù)e = 2 #關鍵字參數(shù)b,c,d = x #列表參數(shù)#錯誤的例子,處理等價于a = 1 #順序參數(shù)b = 2 #關鍵字參數(shù)b,c,d = x #列表參數(shù)#這里由于b多次賦值導致異常,可見只有順序參數(shù)和列表參數(shù)存在羅輯先后關系

函數(shù)聲明區(qū)別

  理解了函數(shù)調用中不同類型參數(shù)得區(qū)別之后,再來理解函數(shù)聲明中不同參數(shù)得區(qū)別就簡單很多了.

1. 函數(shù)聲明中的參數(shù)類型說明


  函數(shù)聲明只有3種類型, arg, *arg , **arg 他們得作用和函數(shù)調用剛好相反. 調用時*tuple_grp_nonkw_args將列表轉換為順序參數(shù),而聲明中的*arg的作用是將順序賦值(positional_args)轉換為列表. 調用時**dict_grp_kw_args將字典轉換為關鍵字參數(shù),而聲明中**arg則反過來將關鍵字參數(shù)(keyword_args)轉換為字典.

特別提醒:*arg 和 **arg可以為空值.

以下舉例說明上述規(guī)則:

#arg, *arg和**arg作用舉例def test2(a,*b,**c):	print a,b,c#---------------------------#*arg 和 **arg可以不傳遞參數(shù)>>> test2(1)1 () {}#arg必須傳遞參數(shù)>>> test2()Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: test2() takes at least 1 argument (0 given)#----------------------------#*arg將順positional_args轉換為列表>>> test2(1,2,[1,2],{'a':1,'b':2})1 (2, [1, 2], {'a': 1, 'b': 2}) {}#該處理等價于a = 1 #arg參數(shù)處理b = 2,[1,2],{'a':1,'b':2} #*arg參數(shù)處理c = dict() #**arg參數(shù)處理print a,b,c#-----------------------------#**arg將keyword_args轉換為字典>>> test2(1,2,3,d={1:2,3:4}, c=12, b=1)1 (2, 3) {'c': 12, 'b': 1, 'd': {1: 2, 3: 4}}#該處理等價于a = 1 #arg參數(shù)處理b= 2,3 #*arg參數(shù)處理#**arg參數(shù)處理c = dict()c['d'] = {1:2, 3:4}c['c'] = 12c['b'] = 1print a,b,c

2. 處理順序問題


  函數(shù)總是先處理arg類型參數(shù),再處理*arg和**arg類型的參數(shù). 因為*arg和**arg針對的調用參數(shù)類型不同,所以不需要考慮他們得順序.

def test2(a,*b,**c):	print a,b,c>>> test2(1, b=[1,2,3], c={1:2, 3:4},a=1)Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: test2() got multiple values for keyword argument 'a'#這里會報錯得原因是,總是先處理arg類型得參數(shù)#該函數(shù)調用等價于#處理arg類型參數(shù):a = 1a = 1  #多次賦值,導致異常#處理其他類型參數(shù)...print a,b,c

閉包

  python的函數(shù),原本只能訪問兩個區(qū)域的變量:全局,和局部(函數(shù)上下文). 實際上,函數(shù)本身也是一個對象,也有自己的作用域. 閉包通過函數(shù)與引用集合的組合,使得函數(shù)可以在它被定義的區(qū)域之外執(zhí)行. 這個集合可以通過func_closure來獲取這個引用集合. 這與python處理全局變量得方式一樣,只不過全局變量將引用集合存儲在__globals__字段中.func_closure是一個存儲cell類型的元組,每個cell存儲一個上下文變量.

  另外,舊版本得python的內部函數(shù)不能在其他作用域使用的原因,并不是因為每個作用域的變量嚴格相互隔離,而是脫離原本的作用域后,函數(shù)失去了原本上下文的引用。需要注意的是,閉包存儲的上下文信息一樣是淺拷貝,所以傳遞給內部函數(shù)的可變對象仍然會被其他擁有該對象引用得變量修改.

舉個例子:

>>> def foo(x,y):...     def bar():...             print x,y...     return bar... #查看func_closure的引用信息>>> a = [1,2]>>> b = foo(a,0)>>> b.func_closure[0].cell_contents[1, 2]>>> b.func_closure[1].cell_contents0>>> b()[1, 2] 0#可變對象仍然能被修改>>> a.append(3)>>> b.func_closure[0].cell_contents[1, 2, 3]>>> b()[1, 2, 3] 0

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 内黄县| 邯郸县| 巍山| 炎陵县| 桂林市| 娄底市| 灌阳县| 青浦区| 天柱县| 张家界市| 百色市| 西平县| 涟源市| 千阳县| 芦溪县| 增城市| 神池县| 织金县| 无为县| 芒康县| 逊克县| 祁连县| 遂昌县| 宕昌县| 大宁县| 林甸县| 普陀区| 平和县| 樟树市| 乐清市| 铜鼓县| 连云港市| 奉新县| 鄯善县| 合山市| 沙雅县| 麻阳| 文化| 逊克县| 清涧县| 鄂州市|