parameter 是函數(shù)定義的參數(shù)形式
在溧水等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需定制網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都全網(wǎng)營銷,外貿(mào)營銷網(wǎng)站建設(shè),溧水網(wǎng)站建設(shè)費(fèi)用合理。
argument 是函數(shù)調(diào)用時傳入的參數(shù)實(shí)體。
對于函數(shù)調(diào)用的傳參模式,一般有兩種:
此外,
也是關(guān)鍵字傳參
python的函數(shù)參數(shù)定義一般來說有五種: 位置和關(guān)鍵字參數(shù)混合 , 僅位置參數(shù) , 僅關(guān)鍵字參數(shù) , 可變位置參數(shù) , 可變關(guān)鍵字參數(shù) 。其中僅位置參數(shù)的方式僅僅是一個概念,python語法中暫時沒有這樣的設(shè)計(jì)。
通常我們見到的函數(shù)是位置和關(guān)鍵字混合的方式。
既可以用關(guān)鍵字又可以用位置調(diào)用
或
這種方式的定義只能使用關(guān)鍵字傳參的模式
f(*some_list) 與 f(arg1, arg2, ...) (其中some_list = [arg1, arg2, ...])是等價的
網(wǎng)絡(luò)模塊request的request方法的設(shè)計(jì)
多數(shù)的可選參數(shù)被設(shè)計(jì)成可變關(guān)鍵字參數(shù)
有多種方法能夠?yàn)楹瘮?shù)定義輸出:
非?;逎?/p>
如果使用可變對象作為函數(shù)的默認(rèn)參數(shù),會導(dǎo)致默認(rèn)參數(shù)在所有的函數(shù)調(diào)用中被共享。
例子1:
addItem方法的data設(shè)計(jì)了一個默認(rèn)參數(shù),使用不當(dāng)會造成默認(rèn)參數(shù)被共享。
python里面,函數(shù)的默認(rèn)參數(shù)被存在__default__屬性中,這是一個元組類型
例子2:
在例子1中,默認(rèn)參數(shù)是一個列表,它是mutable的數(shù)據(jù)類型,當(dāng)它寫進(jìn) __defauts__屬性中時,函數(shù)addItem的操作并不會改變它的id,相當(dāng)于 __defauts__只是保存了data的引用,對于它的內(nèi)存數(shù)據(jù)并不關(guān)心,每次調(diào)用addItem,都可以修改 addItem.__defauts__中的數(shù)據(jù),它是一個共享數(shù)據(jù)。
如果默認(rèn)參數(shù)是一個imutable類型,情況將會不一樣,你無法改變默認(rèn)參數(shù)第一次存入的值。
例子1中,連續(xù)調(diào)用addItem('world') 的結(jié)果會是
而不是期望的
python 的函數(shù)參數(shù)類型分為4種:
1.位置參數(shù):調(diào)用函數(shù)時根據(jù)函數(shù)定義的參數(shù)位置來傳遞參數(shù),位置參數(shù)也可以叫做必要參數(shù),函數(shù)調(diào)用時必須要傳的參數(shù)。
當(dāng)參數(shù)滿足函數(shù)必要參數(shù)傳參的條件,函數(shù)能夠正常執(zhí)行:
add(1,2) #兩個參數(shù)的順序必須一一對應(yīng),且少一個參數(shù)都不可以
當(dāng)我們運(yùn)行上面的程序,輸出:
當(dāng)函數(shù)需要兩個必要參數(shù),但是調(diào)用函數(shù)只給了一個參數(shù)時,程序會拋出異常
add(1)
當(dāng)我們運(yùn)行上面的程序,輸出:
當(dāng)函數(shù)需要兩個必要參數(shù),但是調(diào)用函數(shù)只給了三個參數(shù)時,程序會拋出異常
add(1,2,3)
當(dāng)我們運(yùn)行上面的程序,輸出
2.關(guān)鍵字參數(shù):用于函數(shù)調(diào)用,通過“鍵-值”形式加以指定??梢宰尯瘮?shù)更加清晰、容易使用,同時也清除了參數(shù)的順序需求。
add(1,2) # 這種方式傳參,必須按順序傳參:x對應(yīng)1,y對應(yīng):2
add(y=2,x=1) #以關(guān)健字方式傳入?yún)?shù)(可以不按順序)
正確的調(diào)用方式
add(x=1, y=2)
add(y=2, x=1)
add(1, y=2)
以上調(diào)用方式都是允許的,能夠正常執(zhí)行
錯誤的調(diào)用方式
add(x=1, 2)
add(y=2, 1)
以上調(diào)用都會拋出SyntaxError 異常
上面例子可以看出:有位置參數(shù)時,位置參數(shù)必須在關(guān)鍵字參數(shù)的前面,但關(guān)鍵字參數(shù)之間不存在先后順序的
3.默認(rèn)參數(shù):用于定義函數(shù),為參數(shù)提供默認(rèn)值,調(diào)用函數(shù)時可傳可不傳該默認(rèn)參數(shù)的值,所有位置參數(shù)必須出現(xiàn)在默認(rèn)參數(shù)前,包括函數(shù)定義和調(diào)用,有多個默認(rèn)參數(shù)時,調(diào)用的時候,既可以按順序提供默認(rèn)參數(shù),也可以不按順序提供部分默認(rèn)參數(shù)。當(dāng)不按順序提供部分默認(rèn)參數(shù)時,需要把參數(shù)名寫上
默認(rèn)參數(shù)的函數(shù)定義
上面示例第一個是正確的定義位置參數(shù)的方式,第二個是錯誤的,因?yàn)槲恢脜?shù)在前,默認(rèn)參數(shù)在后
def add1(x=1,y) 的定義會拋出如下異常
默認(rèn)參數(shù)的函數(shù)調(diào)用
注意:定義默認(rèn)參數(shù)默認(rèn)參數(shù)最好不要定義為可變對象,容易掉坑
不可變對象:該對象所指向的內(nèi)存中的值不能被改變,int,string,float,tuple
可變對象,該對象所指向的內(nèi)存中的值可以被改變,dict,list
這里只要理解一下這個概念就行或者自行百度,后續(xù)會寫相關(guān)的專題文章講解
舉一個簡單示例
4.可變參數(shù)區(qū)別:定義函數(shù)時,有時候我們不確定調(diào)用的時候會多少個參數(shù),j就可以使用可變參數(shù)
可變參數(shù)主要有兩類:
*args: (positional argument) 允許任意數(shù)量的可選位置參數(shù)(參數(shù)),將被分配給一個元組, 參數(shù)名前帶*,args只是約定俗成的變量名,可以替換其他名稱
**kwargs:(keyword argument) 允許任意數(shù)量的可選關(guān)鍵字參數(shù),,將被分配給一個字典,參數(shù)名前帶**,kwargs只是約定俗成的變量名,可以替換其他名稱
*args 的用法
args 是用來傳遞一個非鍵值對的可變數(shù)量的參數(shù)列表給函數(shù)
語法是使用 符號的數(shù)量可變的參數(shù); 按照慣例,通常是使用arg這個單詞,args相當(dāng)于一個變量名,可以自己定義的
在上面的程序中,我們使用* args作為一個可變長度參數(shù)列表傳遞給add()函數(shù)。 在函數(shù)中,我們有一個循環(huán)實(shí)現(xiàn)傳遞的參數(shù)計(jì)算和輸出結(jié)果。
還可以直接傳遞列表或者數(shù)組的方式傳遞參數(shù),以數(shù)組或者列表方式傳遞參數(shù)名前面加(*) 號
理解* * kwargs
**kwargs 允許你將不定長度的鍵值對, 作為參數(shù)傳遞給函數(shù),這些關(guān)鍵字參數(shù)在函數(shù)內(nèi)部自動組裝為一個dict
下篇詳細(xì)講解 *args, **kwargs 的參數(shù)傳遞和使用敬請關(guān)注
python中的函數(shù),大多需要配置參數(shù),以下是幾種函數(shù)的參數(shù)類型:
1.必備參數(shù):以正確的順序、個數(shù)傳入函數(shù)。調(diào)用時的參數(shù)情況要和聲明時一樣。最常用的情況。
def tplink(a,b):
c=a+b+b
return c?
tplink(4,2)
2.關(guān)鍵字參數(shù):使用關(guān)鍵字參數(shù)允許函數(shù)調(diào)用時參數(shù)的順序和聲明時不一致,因?yàn)閜ython解析器會在調(diào)用函數(shù)時,用參數(shù)名匹配參數(shù)值。
def tplink(age1,age2):
ageall=age1+age2+age2
return ageall
tplink(age2=4,age1=2)
3.默認(rèn)參數(shù):默認(rèn)某個參數(shù)的取值
def tplink(age1,age2=5):
ageall=age1+age2+age2
return ageall
tplink(age1=4)
4.不定長參數(shù):在聲明時并不確定 調(diào)用時的參數(shù)數(shù)量。這種情況,可以用不定長參數(shù)進(jìn)行解決,具體操作是在參數(shù)名前用*。
但不能和 關(guān)鍵字參數(shù)并用。一般在正常參數(shù)arg之后。
*args、**kwargs的定義:
這兩個都是python中的不定長參數(shù),又稱為可變參數(shù)。
*args 表示任何多個無名參數(shù),它是一個 tuple ;
**kwargs 表示關(guān)鍵字參數(shù),它是一個dict。
同時使用 * args和 ** kwargs 時,必須 * args參數(shù)列要在 ** kwargs前。且都在arg之后。
函數(shù)在調(diào)用時,會根據(jù)順序,看是否放進(jìn) *args 或者 **kwargs中。
具體可根據(jù)實(shí)際情況使用,可以 更方便靈活的接收信息。
python有兩個內(nèi)置的函數(shù)用于實(shí)現(xiàn)排序,一個是list.sort()函數(shù),一個是sorted()函數(shù)。
區(qū)別1:list.sort()函數(shù)只能處理list類型數(shù)據(jù)的排序;sorted()則可以處理多種類型數(shù)據(jù)的排序。
區(qū)別2:list.sort()會修改原來的list為排序后的結(jié)果;sorted()不會修改原來的數(shù)據(jù),只是返回一個排序后的對象。
下面來動手寫點(diǎn)代碼進(jìn)行測試:
list進(jìn)行簡單的排序
1 a=['a','f','c','x','e']2 a.sort()3 a4 [a','c','e','f','x']
sorted()進(jìn)行簡單排序
1 a=['a','f','c','x','e']2 a_new=sorted(a)3 a_new4 ['a', 'c', 'e', 'f', 'x']
list.sort()和sorted都有默認(rèn)的參數(shù)reverse,該參數(shù)的默認(rèn)值為“False”,即默認(rèn)升序排列。如果要進(jìn)行降序排列:
1 a=['a','f','c','x','e']2 a_new=sorted(a,reverse=True)3 a_new4 ['x', 'f', 'e', 'c', 'a']
對元組進(jìn)行排列,不能使用list.sort()函數(shù):
1 a=('a','f','c','x','e')2 a_new=a.sort()3
4 ttributeError: 'tuple' object has no attribute 'sort'
對字典的排序可以按照字典的key或者value進(jìn)行排序:
1 dic={"aa":11,"ff":5,"ee":22}2 printsorted(dic.keys())3 ['aa', 'ee', 'ff']
從python2.4開始list.sort()和sorted()都引入了key參數(shù)來指定一個函數(shù)進(jìn)行排序,有了key參數(shù)以后我們就可以對更加復(fù)雜的數(shù)據(jù)進(jìn)行排序 。
假如需要排序的數(shù)據(jù)為一個list,但list的每一個元素都是一個字典,排序的方法如下:
dic=[{"name":"sunny","age":20},
{"name":"bell","age":5},
{"name":"jim","age":1},
{"name":"jan","age":10}]print sorted(dic,key=lambda arg:arg.get('age'),reverse=False) #按照每個字典的age的值進(jìn)行排序,字典的方法dict.get(key)將返回指定鍵的值。
#輸出結(jié)果為:[{'age': 1, 'name': 'jim'}, {'age': 5, 'name': 'bell'}, {'age': 10, 'name': 'jan'}, {'age': 20, 'name': 'sunny'}]
print sorted(dic,key=lambda arg:arg.get('name'),reverse=False) #按照每個字典的name的值進(jìn)行排序
#輸出結(jié)果為:[{'age': 5, 'name': 'bell'}, {'age': 10, 'name': 'jan'}, {'age': 1, 'name': 'jim'}, {'age': 20, 'name': 'sunny'}]
假如需要排序的數(shù)據(jù)為一個二維的list,即list的每一個元素也是一個list,方法與上面的例子類似:
a=[['100','8','30'],['200','5','50'],['300','1','20']]print sorted(a,key=lambda arg:arg[1]) #按照每個list的第1個元素進(jìn)行排序
[['300', '1', '20'], ['200', '5', '50'], ['100', '8', '30']]
前面的2個例子中,key參數(shù)的值都是函數(shù)。在sorted函數(shù)中,key參數(shù)后面的函數(shù)的參數(shù)的數(shù)量只能是一個。lambda arg:arg.get('age')是一個lambda匿名函數(shù),它是一個沒有函數(shù)名的單語句函數(shù)。冒號左邊是參數(shù),冒號右邊的返回值,返回值將被用于排序。
當(dāng)參數(shù)為*arg時,表示接受一個元組;
當(dāng)參數(shù)為**arg時,表示接受一個字典
1. 不同類型的參數(shù)簡述
#這里先說明python函數(shù)調(diào)用得語法為:
復(fù)制代碼
代碼如下:
func(positional_args,
keyword_args,
*tuple_grp_nonkw_args,
**dict_grp_kw_args)
#為了方便說明,之后用以下函數(shù)進(jìn)行舉例
def test(a,b,c,d,e):
print a,b,c,d,e
舉個例子來說明這4種調(diào)用方式得區(qū)別:
復(fù)制代碼
代碼如下:
#
#positional_args方式
test(1,2,3,4,5)
1 2 3 4 5
#這種調(diào)用方式的函數(shù)處理等價于
a,b,c,d,e = 1,2,3,4,5
print 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=1
b=3
c=4
d=2
e=1
print a,b,c,d,e
#
#*tuple_grp_nonkw_args方式
x = 1,2,3,4,5
test(*x)
1 2 3 4
5
#這種方式函數(shù)處理等價于
復(fù)制代碼
代碼如下:
a,b,c,d,e = x
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不再贅述
a,b,c,d,e
2.
不同類型參數(shù)混用需要注意的一些細(xì)節(jié)
接下來說明不同參數(shù)類型混用的情況,要理解不同參數(shù)混用得語法需要理解以下幾方面內(nèi)容.
首先要明白,函數(shù)調(diào)用使用參數(shù)類型必須嚴(yán)格按照順序,不能隨意調(diào)換順序,否則會報錯. 如 (a=1,2,3,4,5)會引發(fā)錯誤,;
(*x,2,3)也會被當(dāng)成非法.
其次,函數(shù)對不同方式處理的順序也是按照上述的類型順序.因?yàn)?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)的邏輯先后關(guān)系:
復(fù)制代碼
代碼如下:
#只有在順序賦值,列表賦值在結(jié)果上存在羅輯先后關(guān)系
#正確的例子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 #關(guān)鍵字參數(shù)
b,c,d = x #列表參數(shù)
#錯誤的例子,處理等價于
a = 1 #順序參數(shù)
b = 2 #關(guān)鍵字參數(shù)
b,c,d = x
#列表參數(shù)
#這里由于b多次賦值導(dǎo)致異常,可見只有順序參數(shù)和列表參數(shù)存在羅輯先后關(guān)系
函數(shù)聲明區(qū)別
理解了函數(shù)調(diào)用中不同類型參數(shù)得區(qū)別之后,再來理解函數(shù)聲明中不同參數(shù)得區(qū)別就簡單很多了.
1. 函數(shù)聲明中的參數(shù)類型說明
函數(shù)聲明只有3種類型, arg, *arg , **arg 他們得作用和函數(shù)調(diào)用剛好相反.
調(diào)用時*tuple_grp_nonkw_args將列表轉(zhuǎn)換為順序參數(shù),而聲明中的*arg的作用是將順序賦值(positional_args)轉(zhuǎn)換為列表.
調(diào)用時**dict_grp_kw_args將字典轉(zhuǎn)換為關(guān)鍵字參數(shù),而聲明中**arg則反過來將關(guān)鍵字參數(shù)(keyword_args)轉(zhuǎn)換為字典.
特別提醒:*arg
和 **arg可以為空值.
以下舉例說明上述規(guī)則:
復(fù)制代碼
代碼如下:
#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轉(zhuǎn)換為列表
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轉(zhuǎn)換為字典
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'] = 12
c['b'] = 1
a,b,c
2. 處理順序問題
函數(shù)總是先處理arg類型參數(shù),再處理*arg和**arg類型的參數(shù).
因?yàn)?arg和**arg針對的調(diào)用參數(shù)類型不同,所以不需要考慮他們得順序.
復(fù)制代碼
代碼如下:
def test2(a,*b,**c):
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ù)調(diào)用等價于
#處理arg類型參數(shù):
a = 1
a = 1
#多次賦值,導(dǎo)致異常
#處理其他類型參數(shù)
...
print a,b,c
def foo(x,y):
... def bar():
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_contents
b()
[1, 2] 0
#可變對象仍然能被修改
a.append(3)
b.func_closure[0].cell_contents
[1, 2, 3]
b()
[1, 2, 3] 0