『壹』 python中不定長參數這樣用對嗎def hh(w,**l,pu='d'): 為什麼
題主你好,
一般來說, python函數中有兩種形式的參數: 位置參數, 關鍵字參數.
位置參數: 說白了就是在函數調用時必傳的,你不給它賦值函數就運行不了.如:
按照之前講的,調用person時,age必須要傳值,name可傳可不傳,所以調用形式可以是:
person(18), 也可以是person(18,"李四") //同時把參數名加上進行調用也可以,即person(age=18,"李四"), person(age=18, name="李四"), person(18,name="李四")這都是合法的,當然如果看著亂,記住一種就好.
**.還有一點需要注意函數定義中,位置參數一定要位於關鍵字參數前,也就是說def person(name="張三",age)這么寫是錯誤的(對於這條約定我是這么理解的, 你想啊假如位置參數位於關鍵字參數前是可行的,則我們在調用person時,即使name就是默認值"張三",我們也要傳值, 因為如果你這么寫,person(18),則18會傳給person的第一個參數name,如果你寫person("張三",18)又麻煩了,因為name的默認值就是"張三', 但我覺得使用person(age=18)還可以理解呀,不管怎麼樣吧,記住規矩就是這樣的.).
-----
下面就該引出題主問題中所謂的"不定長參數"了. 我感覺叫"任意數量的參數"更好理解一些,因為重點在於數量,而不在於長度.//至少如果我沒有看到你的實際題目,你說"不定長參數"我會理解為一個參數的值的長度不限, 而非可以有任意多個參數.
為了迎合題主, 下面就稱"不定長參數"吧.
python中一般不定長參數有兩種類型,位置不定長參數和關鍵字不定長參數, 其外在特徵是:
位置不定長參數由一個星號+變數名組成: *var //var是我隨意寫的,可以是*a,*b,*any等
關鍵字不定長參數由兩個星號+變數名組成: **key //同理,key也可以是任意名稱.
-----
不定長參數的出現其實就是為了增加函數的靈活性, 這個靈活性就體現在"可以表示任意多個參數位置參數和或關鍵字參數".
-----
最後再說回題主的問題:
def hh(w,**l,pu='d')
這個用法不對, pu='d'要放在**l前面,我說下原因:
先看一下hh這個函數中的參數類型有兩種, w是位置參數; **l和pu='d'是關鍵字參數.
因此w放在最前面沒毛病(位置參數要位於關鍵字參數前面), 而為什麼pu='d'要放在**l前面呢,因為**l表示所有的關鍵字參數都要傳給l,所以如果pu='d'寫在**l後面,則pu='d'就不起作用了,因此不能這樣寫.
=====
希望可以幫到題主, 歡迎追問.
『貳』 python-函數可變參數類型
python中的函數,大多需要配置參數,以下是幾種函數的參數類型:
1.必備參數:以正確的順序、個數傳入函數。調用時的參數情況要和聲明時一樣。最常用的情況。
def tplink(a,b):
c=a+b+b
return c
tplink(4,2)
2.關鍵字參數:使用關鍵字參數允許函數調用時參數的順序和聲明時不一致,因為python解析器會在調用函數時,用參數名匹配參數值。
def tplink(age1,age2):
ageall=age1+age2+age2
return ageall
tplink(age2=4,age1=2)
3.默認參數:默認某個參數的取值
def tplink(age1,age2=5):
ageall=age1+age2+age2
return ageall
tplink(age1=4)
4.不定長參數:在聲明時並不確定 調用時的參數數量。這種情況,可以用不定長參數進行解決,具體操作是在參數名前用*。
但不能和 關鍵字參數並用。一般在正常參數arg之後。
*args、**kwargs的定義:
這兩個都是python中的不定長參數,又稱為可變參數。
*args 表示任何多個無名參數,它是一個 tuple ;
**kwargs 表示關鍵字參數,它是一個dict。
同時使用 * args和 ** kwargs 時,必須 * args參數列要在 ** kwargs前。且都在arg之後。
函數在調用時,會根據順序,看是否放進 *args 或者 **kwargs中。
具體可根據實際情況使用,可以 更方便靈活的接收信息。
『叄』 Python函數的參數類型
Python函數的參數類型主要包括必選參數、可選參數、可變參數、位置參數和關鍵字參數,本文介紹一下他們的定義以及可變數據類型參數傳遞需要注意的地方。
必選參數(Required arguments)是必須輸入的參數,比如下面的代碼,必須輸入2個參數,否則就會報錯:
其實上面例子中的參數 num1和num2也屬於關鍵字參數,比如可以通過如下方式調用:
執行結果:
可選參數(Optional arguments)可以不用傳入函數,有一個默認值,如果沒有傳入會使用默認值,不會報錯。
位置參數(positional arguments)根據其在函數定義中的位置調用,下面是pow()函數的幫助信息:
x,y,z三個參數的的順序是固定的,並且不能使用關鍵字:
輸出:
在上面的pow()函數幫助信息中可以看到位置參數後面加了一個反斜杠 / ,這是python內置函數的語法定義,Python開發人員不能在python3.8版本之前的代碼中使用此語法。但python3.0到3.7版本可以使用如下方式定義位置參數:
星號前面的參數為位置參數或者關鍵字參數,星號後面是強制關鍵字參數,具體介紹見強制關鍵字參數。
python3.8版本引入了強制位置參數(Positional-Only Parameters),也就是我們可以使用反斜杠 / 語法來定義位置參數了,可以寫成如下形式:
來看下面的例子:
python3.8運行:
不能使用關鍵字參數形式賦值了。
可變參數 (varargs argument) 就是傳入的參數個數是可變的,可以是0-n個,使用星號( * )將輸入參數自動組裝為一個元組(tuple):
執行結果:
關鍵字參數(keyword argument)允許將任意個含參數名的參數導入到python函數中,使用雙星號( ** ),在函數內部自動組裝為一個字典。
執行結果:
上面介紹的參數可以混合使用:
結果:
注意:由於傳入的參數個數不定,所以當與普通參數一同使用時,必須把帶星號的參數放在最後。
強制關鍵字參數(Keyword-Only Arguments)是python3引入的特性,可參考:https://www.python.org/dev/peps/pep-3102/。 使用一個星號隔開:
在位置參數一節介紹過星號前面的參數可以是位置參數和關鍵字參數。星號後面的參數都是強制關鍵字參數,必須以指定參數名的方式傳參,如果強制關鍵字參數沒有設置默認參數,調用函數時必須傳參。
執行結果:
也可以在可變參數後面命名關鍵字參數,這樣就不需要星號分隔符了:
執行結果:
在Python對象及內存管理機制中介紹了python中的參數傳遞屬於對象的 引用傳遞 (pass by object reference),在編寫函數的時候需要特別注意。
先來看個例子:
執行結果:
l1 和 l2指向相同的地址,由於列表可變,l1改變時,l2也跟著變了。
接著看下面的例子:
結果:
l1沒有變化!為什麼不是[1, 2, 3, 4]呢?
l = l + [4]表示創建一個「末尾加入元素 4「的新列表,並讓 l 指向這個新的對象,l1沒有進行任何操作,因此 l1 的值不變。如果要改變l1的值,需要加一個返回值:
結果:
下面的代碼執行結果又是什麼呢?
執行結果:
和第一個例子一樣,l1 和 l2指向相同的地址,所以會一起改變。這個問題怎麼解決呢?
可以使用下面的方式:
也可以使用淺拷貝或者深度拷貝,具體使用方法可參考Python對象及內存管理機制。這個問題在Python編程時需要特別注意。
本文主要介紹了python函數的幾種參數類型:必選參數、可選參數、可變參數、位置參數、強制位置參數、關鍵字參數、強制關鍵字參數,注意他們不是完全獨立的,比如必選參數、可選參數也可以是關鍵字參數,位置參數可以是必選參數或者可選參數。
另外,python中的參數傳遞屬於對象的 引用傳遞 ,在對可變數據類型進行參數傳遞時需要特別注意,如有必要,使用python的拷貝方法。
參考文檔:
--THE END--
『肆』 【Python】基礎總結
input("提示性信息")
如:
input("請輸入數字")
因為 Python 沒有特別人為規定數據類型,數據類型是由計算機進行判定,所以我們 input() 輸入的數據均默認作為字元串處理,而如果要輸入一些數字,著需要 eval() 評估函數對字元串進行評估,化為語句(數字)。
print(...)
默認空一行,如果想不空行,則
print(...., end = "")
特性:
進制:
特性:
浮點數間運算存在不確定尾數,不是 bug
如:0.1+0.3 → 0.4
0.1+0.2 → 0.30000000000000004
這是由於在計算機中一切數據都是化為二進制進行存儲的,而有的浮點數並不能完全化為相等的二進制數,只能無限趨近於二進制數。
如:0.1 →
解決方法:
四捨五入:
例如:z = 1.23e-4 + 5.6e+89j
z.real 獲得實部,z.imag 獲得虛部
三種類型存在一種逐漸「擴展」或「變寬」的關系:
整數 → 浮點數 → 復數
特點:
字元串有 2 類共 4 種表示方法:
擴展:
使用[]獲取字元串中一個或多個字元
使用[M:N:K]根據步長對字元串切片
{<參數序號>:<格式控制標記>}
> 右對齊
^ 居中對齊 | 槽設定的輸出寬度 | 數字的千位分隔符 | 浮點數小數精度 或 字元串最大輸出長度 | 整數類型
b , c , d , o , x , X
浮點數類型
e , E , f , % |
填充、對齊、寬度這三個一組,例如:
"{0:=^20}".format("PYTHON")
→ '=======PYTHON======='
"{0:*>20}".format("BIT")
→ '*****************BIT'
"{:10}".format("BIT")
'BIT '
剩下的三個一組,例如:
"{0:,.2f}".format(12345.6789)
→ ,345.68'
"{0:b},{0:c},{0:d},{0:o},{0:x},{0:X}x".format(425)
→ ,Σ,425,651,1a9,1A9'
"{0:e},{0:E},{0:f},{0:%}".format(3.14)
Ɖ.140000e+00,3.140000E+00,3.140000,314.000000%'
↓CloseCode↓
使用 raise 語句拋出一個指定的異常。
raise [Exception [, args [, traceback]]]
緊湊形式:適用於簡單表達式的二分支結構
<表達式1> if <條件> else <表達式2>
例如:
↓CloseCode↓
↓CloseCode↓
↓CloseCode↓
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
由條件控制的循環運行方式
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
↓CloseCode↓
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
↓CloseCode↓
可選參數例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
可變參數例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
在函數定義中,經常會碰到 *args(arguments) 和作為參數 **kwargs(keyword arguments)。
(事實上在函數中,和才是必要的,args 和 kwargs 可以用其他名稱代替)
*args 是指不定數量的非鍵值對參數。
**kwargs 是指不定數量的鍵值對參數。
*args 作為作為元組匹配沒有指定參數名的參數。而 **kwargs 作為字典,匹配指定了參數名的參數。
*args 必須位於 **kwargs 之前。
args( 通常緊跟一個標識符,你會看到a或者args都是標識符)是python用於接收或者傳遞任意基於位置的參數的語法。當你接收到一個用這種語法描敘參數時(比如你在函數def語句中對函數簽名使用了星號語法),python會將此標識符綁定到一個元祖,該元祖包含了所有基於位置的隱士的接收到的參數。當你用這種語法傳遞參數時,標識符可以被綁定到任何可迭代對象(事實上,它也可以是人和表達式,並不必須是一個標識符),只要這個表達式的結果是一個可迭代的對象就行。
**kwds(標識符可以是任意的,通常k或者kwds表示)是python用於接收或者傳遞任意基於位置的參數的語法。(python有時候會將命名參數稱為關鍵字參數,他們其實並不是關鍵字--只是用他們來給關鍵字命名,比如pass,for或者yield,還有很多,不幸的是,這種讓人疑惑的術語目前仍是這門語言極其文化根深蒂固的一個組成部分。)當你接收到用這種語法描敘的一個參數時(比如你在函數的def語句中對函數簽名使用了雙星號語法)python會將標識符綁定到一個字典,該字典包含了所有接收到的隱士的命名參數。當你用這種語法傳遞參數時,標識符只能被綁定到字典(我ID號I它也可以是表達式,不一定是一個標識符,只要這個表達式的結果是一個字典即可)。
當你在定義或調用一個函數的時候,必須確保a和k在其他所有參數之後。如果這兩者同時出現,要將k放在a之後。
lambda函數返回函數名作為結果
↓CloseCode↓
例如:
↓CloseCode↓
運行結果:
↓CloseCode↓
謹慎使用lambda函數
『伍』 Python的函數和參數
parameter 是函數定義的參數形式
argument 是函數調用時傳入的參數實體。
對於函數調用的傳參模式,一般有兩種:
此外,
也是關鍵字傳參
python的函數參數定義一般來說有五種: 位置和關鍵字參數混合 , 僅位置參數 , 僅關鍵字參數 , 可變位置參數 , 可變關鍵字參數 。其中僅位置參數的方式僅僅是一個概念,python語法中暫時沒有這樣的設計。
通常我們見到的函數是位置和關鍵字混合的方式。
既可以用關鍵字又可以用位置調用
或
這種方式的定義只能使用關鍵字傳參的模式
f(*some_list) 與 f(arg1, arg2, ...) (其中some_list = [arg1, arg2, ...])是等價的
網路模塊request的request方法的設計
多數的可選參數被設計成可變關鍵字參數
有多種方法能夠為函數定義輸出:
非常晦澀
如果使用可變對象作為函數的默認參數,會導致默認參數在所有的函數調用中被共享。
例子1:
addItem方法的data設計了一個默認參數,使用不當會造成默認參數被共享。
python裡面,函數的默認參數被存在__default__屬性中,這是一個元組類型
例子2:
在例子1中,默認參數是一個列表,它是mutable的數據類型,當它寫進 __defauts__屬性中時,函數addItem的操作並不會改變它的id,相當於 __defauts__只是保存了data的引用,對於它的內存數據並不關心,每次調用addItem,都可以修改 addItem.__defauts__中的數據,它是一個共享數據。
如果默認參數是一個imutable類型,情況將會不一樣,你無法改變默認參數第一次存入的值。
例子1中,連續調用addItem('world') 的結果會是
而不是期望的
『陸』 Python review
Python的一個簡單review
Python重要特點就是對象模型的一致性,Python解釋器中的任何數值,字元串,數據結構,函數,類,模塊,都是一種Python對象,每個對象都有一個與之相關的類型比如字元串和函數以及內部數據,幾乎所有的Python對象都有一些附屬函數,也就是方法,他們可以訪問對象內部的數據,函數既可以接受位置參數,也可以接受關鍵字參數
在Python中對變數賦值的時候,其實是創建等號右側對象的一個引用
def append_element(some_list,element):
some_list.append(element)
append_element(a,5)
print b```
Python中的對象引用沒有與之相關聯的類型信息,變數其實就是對象在特定命名空間中的名稱,對象的類型信息是保存在它自己內部的,Python可以被認為是一種強類型語言,所有對象都有一個特定的類型,隱式轉換只在很明顯的情況下才會發生
def isiterable(obj):
try:
iter(obj)
print "True"
except:
print "False"
isiterable(a)
isiterable(a[1])
if not isinstance(a,list) and isiterable(a):
a = list(a)```
判斷兩個引用是否指向同一個對象,可以使用is,或者is not
print 3 // 2
print 3/2
print 1 + 2j```
許多Python對象可以用str函數將其轉換為字元串
字元串可以被當作序列類型進行處理
在字元串的左邊加上r表示按照原本的樣子進行解釋
None是NoneType的一個實例
tup = 4,5,6
print tup
nested_tup = (1,2,3),(5,6)
print nested_tup
print tuple([2,3,4])
a,b,c = tup
print a,b,c
tup = 4,5,(6,7)
a,b,(c,d) = tup
print a,b,c,d
a,b = b,a
print a,b
a = (1,2,3,2,2,3,4,5)
print a.count(2)```
列表
是可變的,通過[]或者list函數定義
print c[:5]
print c[-1:-3]
print c[::-1]
c.reverse()
print c
reverse_list = []
for i in reversed(c):
reverse_list.append(i)
print reverse_list```
內置的序列函數
d1 = {"a":'some_value','b':[1,2,3,4]}
print d1
for key,value in zip(d1.keys(),d1.values()):
print key,value
d1.pop('a')
print d1
d1.update({'c':"foo",'d':12})
print d1```
建立字典
strings = ['a','as','asd','bat']
print [x.upper() for x in strings if len(x) > 2]
print {key:value for value,key in enumerate(strings)}
print dict((key,value) for value,key in enumerate(strings))
some_tuples = [(1,2,3),(4,5,6)]
flattened = [x for tup in some_tuples for x in tup]
print flattened
print [[x for x in tup] for tup in some_tuples]```
函數
關鍵字參數必須位於位置參數之後,可以任何順序指定關鍵字參數
雖然可以在函數中對全局變數進行賦值操作,但是那些變數必須用global關鍵字聲明為全局
def make_closure(a):
def closure():
print "I dont know "+str(a)
return closure
closure = make_closure(5)
closure()
函數的位置和關鍵字參數是分別被打包成元組和字典的,函數實際接受到的是一個元組args
和一個字典kwargs
部分參數應用
def squares(n=10):
for i in range(1,n+1):
yield i ** 2
for i in squares():
print i,
gen = (x**3 for x in range(10))
for x in gen:
print x,
print list(x ** 2 for x in range(10))
print dict((i,i**2) for i in range(5))```
文件和操作系統
open函數,r,a,w,
with
seek,tell,read字元串方式返迴文件數據,readlines返回行列表,write
『柒』 python // 與 / * 和 ** 運算符 的含義
1 在 Python 2.2 :
要引用: from __future__ import division
" / "就表示 浮點數除法,返回浮點結果;" // "表示整數除法。
2 Python 3以後 :
" / "就表示 浮點數除法,返回浮點結果;" // "表示整數除法。
python //10 除以10 然後向下取整
在 Python 中,* 和 ** 具有語法多義性,具體來說是有四類用法。
1. 算數運算
* 代表乘法
** 代表乘方
>>> 2*5
10
>>> 2**5
32
2. 函數形參
*args 和 **kwargs 主要用於函數定義。
你可以將不定數量的參數傳遞給一個函數。不定的意思是:預先並不知道, 函數使用者會傳遞多少個參數給你, 所以在這個場景下使用這兩個關鍵字。其實並不是必須寫成 *args 和 **kwargs。 *(星號) 才是必須的. 你也可以寫成 *ar 和 **k 。而寫成 *args 和**kwargs 只是一個通俗的命名約定。
python函數傳遞參數的方式有兩種:
位置參數(positional argument)
關鍵詞參數(keyword argument)
*args 與 **kwargs 的區別,兩者都是 python 中的可變參數:
*args 表示任何多個無名參數,它本質是一個 tuple
**kwargs 表示關鍵字參數,它本質上是一個 dict
如果同時使用 *args 和 **kwargs 時,必須 *args 參數列要在 **kwargs 之前。
>>> deffun(*args, **kwargs):
... print('args=', args)
... print('kwargs=', kwargs)
...
>>> fun(1,2,3,4, A='a', B='b', C='c', D='d')
args= (1,2,3,4)
kwargs= {'A':'a','B':'b','C':'c','D':'d'}
使用 *args
>>> deffun(name, *args):
... print('你好:', name)
... foriinargs:
... print("你的寵物有:", i)
...
>>> fun("Geek","dog","cat")
你好: Geek
你的寵物有: dog
你的寵物有: cat
使用 **kwargs
>>> deffun(**kwargs):
... forkey, valueinkwargs.items():
... print("{0} 喜歡 {1}".format(key, value))
...
>>> fun(Geek="cat", cat="box")
Geek 喜歡 cat
cat 喜歡 box
3. 函數實參
如果函數的形參是定長參數,也可以使用 *args 和 **kwargs 調用函數,類似對元組和字典進行解引用:
>>> deffun(data1, data2, data3):
... print("data1: ", data1)
... print("data2: ", data2)
... print("data3: ", data3)
...
>>> args = ("one",2,3)
>>> fun(*args)
data1: one
data2:2
data3:3
>>> kwargs = {"data3":"one","data2":2,"data1":3}
>>> fun(**kwargs)
data1:3
data2:2
data3: one
4. 序列解包
>>> a, b, *c =0,1,2,3
>>> a
0
>>> b
1
>>> c
[2,3]
『捌』 Python參數類型
上一期我們學習參數傳遞怎麼傳遞,也了解了參數的幾種類型。
首先,我們再來回顧一下,形參和實參:
形參是在定義函數時定義的,放在函數名後面的圓括弧里,可為空
實參是調用函數時為形參傳入具體的參數值
簡單總結一下,誰調用函數,誰就負責傳入參數。
好吶,本期我們來詳細學習函數幾種參數類型,大綱如下:
python函數的參數名是無意義的,Python允許在調用函數時通過通過名字來傳入參數值。
位置參數:按照形參位置傳入的參數
調用函數時,實參默認按位置順序傳遞的。同時實參個數也要和形參匹配
舉一個小栗子
如果實參的個數與形參不匹配時,調用函數運行就會報錯
Python中,形參與調用函數緊密聯系在一起的。
關鍵字參數:調用函數時,使形參名稱來傳遞參數,形式為「形參名=實參」
關鍵字參數,又叫命名參數,傳遞時無需考慮參數位置和順序
舉一個小栗子
默認參數:定義函數時,我們可以為形參提前設置具體的值。
在定義函數時,默認參數要放到位置等其他參數後面
在調用函數時,默認參數是可選的。如果傳入新值,則會覆蓋默認值
舉一個小栗子
注意,默認值不能位於位置參數前面,否則程序會報錯誤
不定長參數又名可變參數。
不定長參數指的是可變數量的參數,分兩種情況:
如果不定長參數後面,可以新增參數嗎?
我們通過例子來看,會發生什麼?
運行上面的程序,Python解釋器會報錯
原因是,形參a已經是不定長參數,我們調用的test(2,3,4)傳入的三個實參,系統自動把它們屬於形參a的值,形參b 和形參c就等於沒有值傳入,這時候系統就認為,調用函數的對象,參數沒有傳夠。
為了解決這一報錯,python引入了 強制命名參數
規定,調用不定參數後面有跟位置參數的函數時,傳入給位置參數時,必須要強制命名參進行傳參。
逆向參數收集針對的對象傳入函數的實參
調用函數時,如果實參是元組,列表或者字典,通過在實參前面加入星號,可以自動把元素進行隔開,然後再轉入給函數進行處理
舉一個小栗子
本期,我們詳細學習了參數幾種類型,為後面我們學習函數,打好基礎。
實踐是檢驗真理的過程,大家多動手練習練習,會有不一樣的奇妙旅程~
好吶,以上是本期內容,歡迎大佬們評論區指正~
『玖』 python中什麼是位置參數
先說說函數定義,我們都知道,下面的代碼定義了一個函數funcA
def funcA():
pass
顯然,函數funcA沒有參數(同時啥也不幹:D)。
下面這個函數funcB就有兩個參數了,
def funcB(a, b):
print a
print b
調用的時候,我們需要使用函數名,加上圓括弧擴起來的參數列表,比如 funcB(100, 99),執行結果是:
100
99
很明顯,參數的順序和個數要和函數定義中一致,如果執行funcB(100),Python會報錯的:
TypeError: funcB() takes exactly 2 arguments (1 given)
我們可以在函數定義中使用參數默認值,比如
def funcC(a, b=0):
print a
print b
在函數funcC的定義中,參數b有默認值,是一個可選參數,如果我們調用funcC(100),b會自動賦值為0。
OK,目前為止,我們要定義一個函數的時候,必須要預先定義這個函數需要多少個參數(或者說可以接受多少個參數)。一般情況下這是沒問題的,但是也有在定義函數的時候,不能知道參數個數的情況(想一想C語言里的printf函數),在Python里,帶*的參數就是用來接受可變數量參數的。看一個例子
def funcD(a, b, *c):
print a
print b
print "length of c is: %d " % len(c)
print c
調用funcD(1, 2, 3, 4, 5, 6)結果是
1
2
length of c is: 4
(3, 4, 5, 6)
我們看到,前面兩個參數被a、b接受了,剩下的4個參數,全部被c接受了,c在這里是一個tuple。我們在調用funcD的時候,至少要傳遞2個參數,2個以上的參數,都放到c里了,如果只有兩個參數,那麼c就是一個empty tuple。
好了,一顆星我們弄清楚了,下面輪到兩顆星。
上面的例子里,調用函數的時候,傳遞的參數都是根據位置來跟函數定義里的參數表匹配的,比如funcB(100, 99)和funcB(99, 100)的執行結果是不一樣的。在Python里,還支持一種用關鍵字參數(keyword argument)調用函數的辦法,也就是在調用函數的時候,明確指定參數值付給那個形參。比如還是上面的funcB(a, b),我們通過這兩種方式調用
funcB(a=100, b=99)
和
funcB(b=99, a=100)
結果跟funcB(100, 99)都是一樣的,因為我們在使用關鍵字參數調用的時候,指定了把100賦值給a,99賦值給b。也就是說,關鍵字參數可以讓我們在調用函數的時候打亂參數傳遞的順序!
另外,在函數調用中,可以混合使用基於位置匹配的參數和關鍵字參數,前題是先給出固定位置的參數,比如
def funcE(a, b, c):
print a
print b
print c
調用funcE(100, 99, 98)和調用funcE(100, c=98, b=99)的結果是一樣的。
好了,經過以上鋪墊,兩顆星總算可以出場了:
如果一個函數定義中的最後一個形參有 ** (雙星號)前綴,所有正常形參之外的其他的關鍵字參數都將被放置在一個字典中傳遞給函數,比如:
def funcF(a, **b):
print a
for x in b:
print x + ": " + str(b[x])
調用funcF(100, c='你好', b=200),執行結果
100
c: 你好
b: 200
大家可以看到,b是一個dict對象實例,它接受了關鍵字參數b和c。
『拾』 python 函數參數類型
python 的函數參數類型分為4種:
1.位置參數:調用函數時根據函數定義的參數位置來傳遞參數,位置參數也可以叫做必要參數,函數調用時必須要傳的參數。
當參數滿足函數必要參數傳參的條件,函數能夠正常執行:
add(1,2) #兩個參數的順序必須一一對應,且少一個參數都不可以
當我們運行上面的程序,輸出:
當函數需要兩個必要參數,但是調用函數只給了一個參數時,程序會拋出異常
add(1)
當我們運行上面的程序,輸出:
當函數需要兩個必要參數,但是調用函數只給了三個參數時,程序會拋出異常
add(1,2,3)
當我們運行上面的程序,輸出
2.關鍵字參數:用於函數調用,通過「鍵-值」形式加以指定。可以讓函數更加清晰、容易使用,同時也清除了參數的順序需求。
add(1,2) # 這種方式傳參,必須按順序傳參:x對應1,y對應:2
add(y=2,x=1) #以關健字方式傳入參數(可以不按順序)
正確的調用方式
add(x=1, y=2)
add(y=2, x=1)
add(1, y=2)
以上調用方式都是允許的,能夠正常執行
錯誤的調用方式
add(x=1, 2)
add(y=2, 1)
以上調用都會拋出SyntaxError 異常
上面例子可以看出:有位置參數時,位置參數必須在關鍵字參數的前面,但關鍵字參數之間不存在先後順序的
3.默認參數:用於定義函數,為參數提供默認值,調用函數時可傳可不傳該默認參數的值,所有位置參數必須出現在默認參數前,包括函數定義和調用,有多個默認參數時,調用的時候,既可以按順序提供默認參數,也可以不按順序提供部分默認參數。當不按順序提供部分默認參數時,需要把參數名寫上
默認參數的函數定義
上面示例第一個是正確的定義位置參數的方式,第二個是錯誤的,因為位置參數在前,默認參數在後
def add1(x=1,y) 的定義會拋出如下異常
默認參數的函數調用
注意:定義默認參數默認參數最好不要定義為可變對象,容易掉坑
不可變對象:該對象所指向的內存中的值不能被改變,int,string,float,tuple
可變對象,該對象所指向的內存中的值可以被改變,dict,list
這里只要理解一下這個概念就行或者自行網路,後續會寫相關的專題文章講解
舉一個簡單示例
4.可變參數區別:定義函數時,有時候我們不確定調用的時候會多少個參數,j就可以使用可變參數
可變參數主要有兩類:
*args: (positional argument) 允許任意數量的可選位置參數(參數),將被分配給一個元組, 參數名前帶*,args只是約定俗成的變數名,可以替換其他名稱
**kwargs:(keyword argument) 允許任意數量的可選關鍵字參數,,將被分配給一個字典,參數名前帶**,kwargs只是約定俗成的變數名,可以替換其他名稱
*args 的用法
args 是用來傳遞一個非鍵值對的可變數量的參數列表給函數
語法是使用 符號的數量可變的參數; 按照慣例,通常是使用arg這個單詞,args相當於一個變數名,可以自己定義的
在上面的程序中,我們使用* args作為一個可變長度參數列表傳遞給add()函數。 在函數中,我們有一個循環實現傳遞的參數計算和輸出結果。
還可以直接傳遞列表或者數組的方式傳遞參數,以數組或者列表方式傳遞參數名前面加(*) 號
理解* * kwargs
**kwargs 允許你將不定長度的鍵值對, 作為參數傳遞給函數,這些關鍵字參數在函數內部自動組裝為一個dict
下篇詳細講解 *args, **kwargs 的參數傳遞和使用敬請關注