自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python編程:定義函數(shù)輸入?yún)?shù)很簡單?這些規(guī)則掌握了沒?

開發(fā) 前端
到目前為止,我們所看到的例子中,看到的所有參數(shù)都是普通的位置參數(shù)或關(guān)鍵字參數(shù)。也已經(jīng)了解了如何將它們作為位置參數(shù)和關(guān)鍵字參數(shù)傳遞。關(guān)于它們沒有太多要說的了,所以我們要來看看其他類別。在此之前,先來看看可選參數(shù)。

?本文內(nèi)容主要涉及如下幾個(gè)主題方法,文章有點(diǎn)長,請(qǐng)收藏以便查閱。

函數(shù)參數(shù)即為函數(shù)的輸入,可分類為五組。

  • 位置或關(guān)鍵字參數(shù):同時(shí)允許位置和關(guān)鍵字參數(shù);
  • 可變位置參數(shù):在元組中收集任意數(shù)量的位置參數(shù);
  • 可變關(guān)鍵字參數(shù):在字典中收集任意數(shù)量的關(guān)鍵字參數(shù);
  • 僅限位置參數(shù):只能作為位置參數(shù)傳遞;
  • 僅限關(guān)鍵字參數(shù):只能作為關(guān)鍵字參數(shù)傳遞。

到目前為止,我們所看到的例子中,看到的所有參數(shù)都是普通的位置參數(shù)或關(guān)鍵字參數(shù)。也已經(jīng)了解了如何將它們作為位置參數(shù)和關(guān)鍵字參數(shù)傳遞。關(guān)于它們沒有太多要說的了,所以我們要來看看其他類別。在此之前,先來看看可選參數(shù)。

1.可選參數(shù)

除了我們?cè)谶@里看到的類別之外,參數(shù)還可以分為必選項(xiàng)和可選項(xiàng)??蛇x參數(shù)有默認(rèn)值,其值在函數(shù)定義中指定。語法是格式為:name=value。示例如下:

# 定義參數(shù)有默認(rèn)值的函數(shù),調(diào)用時(shí)其為可選型參數(shù)
def func(a, b=4, c=88):
print(a, b, c)

func(1) # prints: 1 4 88
func(b=5, a=7, c=9) # prints: 7 5 9
func(42, c=9) # prints: 42 4 9
func(42, 43, 44) # prints: 42, 43, 44

這里,a是必需傳遞參數(shù)項(xiàng),而b的默認(rèn)值是4,c的默認(rèn)值是88,兩者是可選項(xiàng)。重要的是要注意,除了只有關(guān)鍵字的形參外,必需型形參必須始終位于函數(shù)定義中所有可選形參的左側(cè)。試著在上面的例子中刪除c的默認(rèn)值,看看會(huì)發(fā)生什么。

2.不定量位置參數(shù)

有時(shí),可能不希望為函數(shù)指定位置參數(shù)的確切數(shù)量,而Python通過使用可變位置參數(shù)提供了實(shí)現(xiàn)這一點(diǎn)的能力。讓我們來看一個(gè)非常常見的用例,minimum()函數(shù)。

這是一個(gè)計(jì)算其輸入值最小值的函數(shù),代碼如下:

# 不定量位置參數(shù)
def minimum(*n):
# print(type(n)) # n 是個(gè)元組
if n: #
mn = n[0]
for value in n[1:]:
if value < mn:
mn = value
print(mn)

minimum(1, 3, -7, 9) # n = (1, 3, -7, 9) - prints: -7
minimum() # n = () - prints: nothing

如上所見,當(dāng)我們定義一個(gè)帶有星號(hào)*的形參時(shí),我們是在告訴Python,當(dāng)函數(shù)被調(diào)用時(shí),這個(gè)形參將收集數(shù)量不定的位置實(shí)參。在函數(shù)中,n是一個(gè)元組??扇∠a中的注釋print(type(n))行,然后運(yùn)行程序并看看輸出。

注意,一個(gè)函數(shù)最多只能有一個(gè)不定量位置參數(shù)——有更多的位置參數(shù)是沒有意義的。Python將無法決定如何劃分它們之間的參數(shù)。您也無法為變量位置參數(shù)指定默認(rèn)值。默認(rèn)值總是一個(gè)空元組。

提示:

是否注意到代碼中是如何用一個(gè)簡單的if n:檢查n是否為空的?這是因?yàn)樵赑ython中,集合對(duì)象在非空時(shí)求值為True,否則為False。元組、集合、列表、字典等等都是如此。

另一件需要注意的事情是,當(dāng)調(diào)用不帶參數(shù)的函數(shù)時(shí),可能想拋出一個(gè)錯(cuò)誤,而不是靜默地什么都不做。在這種情況下,我們不關(guān)心如何使這個(gè)函數(shù)健壯,而是要理解可變量位置參數(shù)。

另外,是否注意到,定義不定量位置形參的語法與可迭代解包的語法非常相似?這并非巧合。畢竟,這兩個(gè)特征互為鏡像。它們也經(jīng)常一起使用,因?yàn)椴欢课恢眯螀⒆屇悴槐負(fù)?dān)心解包的可迭代對(duì)象的長度是否與函數(shù)定義中的形參數(shù)量相匹配。

3.不定量關(guān)鍵字參數(shù)

不定量關(guān)鍵字參數(shù)(Variable keyword parameters)非常類似于不定量位置參數(shù)。唯一的區(qū)別是語法(**而不是*)和它們以字典形式被收集的事實(shí):

# 不定量關(guān)鍵字參數(shù)
def func(**kwargs):
print(kwargs)

func(a=1, b=42) # prints {'a': 1, 'b': 42}
func() # prints {}
func(a=1, b=46, c=99) # prints {'a': 1, 'b': 46, 'c': 99}

如上所示,在函數(shù)定義的參數(shù)名稱前添加**告訴Python使用該名稱來收集數(shù)量不定的關(guān)鍵字參數(shù)。與不定量位置參數(shù)的情況一樣,每個(gè)函數(shù)最多只能有一個(gè)可變關(guān)鍵字參數(shù),并且不能指定默認(rèn)值。

就像可變量位置參數(shù)類似于可迭代解包一樣,可變關(guān)鍵字參數(shù)類似于字典解包。字典解包也經(jīng)常用于將參數(shù)傳遞給具有可變量關(guān)鍵字形參的函數(shù)。

為什么能夠傳遞可變數(shù)量的關(guān)鍵字參數(shù)如此重要,目前可能還不清楚,那么通過如何使用這一能力的示例,你將能更真實(shí)的理解其重要性。

我們定義一個(gè)連接到數(shù)據(jù)庫的函數(shù):我們希望通過不帶參數(shù)地調(diào)用這個(gè)函數(shù)來連接到默認(rèn)數(shù)據(jù)庫。還希望通過向函數(shù)傳遞適當(dāng)?shù)膮?shù)來連接到任何其他數(shù)據(jù)庫。在你繼續(xù)讀下去之前,自己試著花幾分鐘自己想出一個(gè)解決方案:

# 可變量關(guān)鍵字參數(shù)
def connect(**options):
conn_params = {
'host': options.get('host', '127.0.0.1'),
'port': options.get('port', 5432),
'user': options.get('user', ''),
'pwd': options.get('pwd', ''),
}
print(conn_params)

# 然后連接數(shù)據(jù)庫(注釋掉的代碼行)
# db.connect(**conn_params)
connect()
connect(host='127.0.0.42', port=5433)
connect(port=5431, user='admin', pwd='super')

注意,在函數(shù)中,我們可以準(zhǔn)備一個(gè)連接參數(shù)字典(conn_params)使用默認(rèn)值作為回退,其允許在函數(shù)調(diào)用時(shí)提供以覆蓋它們。有更好的方法可以用更少的代碼行來實(shí)現(xiàn)這一點(diǎn),但我們現(xiàn)在不關(guān)心這一點(diǎn)。運(yùn)行上述代碼會(huì)得到以下結(jié)果:

{'a': 1, 'b': 46, 'c': 99}
{'host': '127.0.0.1', 'port': 5432, 'user': '', 'pwd': ''}
{'host': '127.0.0.42', 'port': 5433, 'user': '', 'pwd': ''}
{'host': '127.0.0.1', 'port': 5431, 'user': 'admin', 'pwd': 'super'}

注意函數(shù)調(diào)用和輸出之間的對(duì)應(yīng)關(guān)系,以及如何根據(jù)傳遞給函數(shù)的內(nèi)容重寫默認(rèn)值。

4.僅限位置參數(shù)

從Python 3.8開始,PEP 570 (https://www.python.org/dev/peps/pep-0570/)引入了僅限位置的參數(shù)。有一種新的函數(shù)參數(shù)語法,/,表示一組函數(shù)形參必須在位置上指定,不能作為關(guān)鍵字參數(shù)傳遞。讓我們看一個(gè)簡單的例子:

# 僅限位置參數(shù)
def func(a, b, /, c):
print(a, b, c)

func(1, 2, 3) # prints: 1 2 3
func(1, 2, c=3) # prints 1 2 3

在上面的例子中,我們定義了一個(gè)函數(shù)func(),它指定了三個(gè)參數(shù):a、b和c。函數(shù)簽名中的/表示a和b必須按位置傳遞,也就是說,不能通過關(guān)鍵字傳遞。

示例中的最后兩行顯示,我們可以按位置傳遞所有三個(gè)參數(shù)來調(diào)用函數(shù),或者可以按關(guān)鍵字傳遞c。這兩種情況都可以正常工作,因?yàn)閏定義在函數(shù)簽名中的/之后。如果我們?cè)噲D通過通過關(guān)鍵字傳遞a或b來調(diào)用函數(shù),像這樣:

func(1, b=2, c=3)

這將產(chǎn)生如下類似回溯跟蹤信息:

Traceback (most recent call last):
File "……", line 9, in <module>
func(1, b=2, c=3)
TypeError: func() got some positional-only arguments passed as keyword arguments: 'b'

前面的例子告訴我們,Python現(xiàn)在反饋給我們調(diào)用func()的方式,其意思是:通過關(guān)鍵字傳遞了參數(shù)b,但不允許這樣做。

僅限位置參數(shù)也可以是可選的,如下所示:

# 可選的僅限位置參數(shù)
def func(a, b=2, /):
print(a, b)

func(4, 5) # prints 4 5
func(3) # prints 3 2

通過一些從官方文檔中借來的例子來看看這個(gè)特性給該語言帶來了什么。一個(gè)優(yōu)點(diǎn)是能夠完全模擬現(xiàn)有C編碼函數(shù)的行為:

def divmod(a, b, /):
"模擬內(nèi)建函數(shù) divmod()"
return (a // b, a % b)

另一個(gè)重要的用例是在形參名沒有啥有意義的幫助的情況下排除關(guān)鍵字實(shí)參:

len(obj='hello')

在上面的例子中,obj關(guān)鍵字參數(shù)降低了可讀性。此外,如果我們希望重構(gòu)len函數(shù)的內(nèi)部結(jié)構(gòu),并將obj重命名為the_object(或任何其他名稱),更改保證不會(huì)破壞任何客戶端代碼,因?yàn)椴粫?huì)有任何對(duì)len()函數(shù)的調(diào)用,會(huì)涉及到現(xiàn)在已經(jīng)過時(shí)的obj參數(shù)名稱。

最后,使用僅限位置形參意味著/左邊的任何值都可以在不定量關(guān)鍵字實(shí)參中使用,如下例所示:

def func_name(name, /, **kwargs):
print(name)
print(kwargs)

func_name('Positional-only name', name='Name in **kwargs')
# 打印輸出為:
# Positional-only name
# {'name': 'Name in **kwargs'}

在函數(shù)簽名中保留參數(shù)名以便在**kwargs中使用的能力可以生成更簡單、更清晰的代碼。

現(xiàn)在來研究一下僅限位置類似版:僅限關(guān)鍵字參數(shù)。

5.僅限關(guān)鍵字參數(shù)

Python 3引入了僅限關(guān)鍵字的參數(shù)。我們只簡要地研究它們,因?yàn)樗鼈兊挠美⒉怀R?。有兩種方法可以指定它們,要么在不定量位置參數(shù)之后,要么在不定的*之后。來看兩個(gè)例子。代碼如下:

# 僅限關(guān)鍵字參數(shù)
def kwo(*a, c):
print(a, c)

kwo(1, 2, 3, c=7) # prints: (1, 2, 3) 7
kwo(c=4) # prints: () 4
# kwo(1, 2) # 此行出問題——無效于法,并有如下錯(cuò)誤
# TypeError: kwo() missing 1 required keyword-only argument: 'c'

def kwo2(a, b=42, *, c):
print(a, b, c)

kwo2(3, b=7, c=99) # prints: 3 7 99
kwo2(3, c=13) # prints: 3 42 13
# kwo2(3, 23) # 此行出問題——無效于法,并有如下錯(cuò)誤
# TypeError: kwo2() missing 1 required keyword-only argument: 'c'

正如預(yù)期的那樣,函數(shù)kwo()接受數(shù)量可變的位置參數(shù)(a)和一個(gè)只有關(guān)鍵字的關(guān)鍵字c。調(diào)用的結(jié)果很簡單,你可以取消對(duì)第三個(gè)調(diào)用的注釋,以查看Python返回什么錯(cuò)誤。

同樣的情況也適用于函數(shù)kwo2(),它與kwo的不同之處在于,它接受一個(gè)位置參數(shù)a、一個(gè)關(guān)鍵字參數(shù)b和一個(gè)只有關(guān)鍵字的參數(shù)c。你可以取消對(duì)第三個(gè)調(diào)用的注釋,以查看產(chǎn)生的錯(cuò)誤。

現(xiàn)在應(yīng)已知道了如何指定不同類型的輸入?yún)?shù),接下來看看如何在函數(shù)定義中組合它們。

6.組合輸入?yún)?shù)

可以在同一個(gè)函數(shù)中組合不同的參數(shù)類型(事實(shí)上,這樣做通常非常有用)。就像在同一個(gè)函數(shù)調(diào)用中組合不同類型的實(shí)參一樣,在順序上有一些限制:

  • 僅限位置的參數(shù)放在前面,然后跟隨一個(gè)斜杠“/”。
  • 普通參數(shù)在任何僅限位置參數(shù)之后。
  • 不定量位置參數(shù)在正常參數(shù)之后。
  • 只有關(guān)鍵字參數(shù)在不定量位置參數(shù)之后。
  • 不定量關(guān)鍵字參數(shù)總是排在最后。

對(duì)于僅限位置參數(shù)和普通參數(shù),任何必需的參數(shù)必須在任何可選參數(shù)之前定義。這意味著,如果你有一個(gè)可選的僅限位置參數(shù),那么所有常規(guī)參數(shù)也必須是可選的。該規(guī)則不影響僅限關(guān)鍵字的參數(shù)。

如果沒有例子,這些規(guī)則可能會(huì)有點(diǎn)難以理解,所以來看幾個(gè)示例:

# 定義個(gè)帶有所有參數(shù)形式的函數(shù)
def func(a, b, c=7, *args, **kwargs):
print('a, b, c:', a, b, c)
print('args:', args)
print('kwargs:', kwargs)

func(1, 2, 3, 5, 7, 9, A='a', B='b')

注意函數(shù)定義中參數(shù)的順序。執(zhí)行該程序會(huì)得到以下結(jié)果:

a, b, c: 1 2 3
args: (5, 7, 9)
kwargs: {'A': 'a', 'B': 'b'}

現(xiàn)在再來看一個(gè)只有關(guān)鍵字參數(shù)的例子:

# 僅限觀自在參數(shù)
def allparams(a, /, b, c=42, *args, d=256, e, **kwargs):
print('a, b, c:', a, b, c)
print('d, e:', d, e)
print('args:', args)
print('kwargs:', kwargs)

allparams(1, 2, 3, 4, 5, 6, e=7, f=9, g=10)

注意,在函數(shù)聲明中有僅限位置形參和僅限關(guān)鍵字形參:a僅限位置形參,而d和e僅限關(guān)鍵字形參。他們是在*args可變量位置參數(shù)之后,如果它們緊跟在單個(gè)*的后面,也會(huì)是一樣的(在這種情況下,將沒有任何可變位置參數(shù))。運(yùn)行程序會(huì)得到以下結(jié)果:

a, b, c: 1 2 3
d, e: 256 7
args: (4, 5, 6)
kwargs: {'f': 9, 'g': 10}

另一件需要注意的事情是我們?yōu)榭勺兞课恢脜?shù)和關(guān)鍵字參數(shù)命名。你可以自由選擇不同的名稱,但請(qǐng)注意,args和kwargs是這些參數(shù)的常規(guī)名稱,至少在一般情況下是這樣。

7.更多的簽名示例

為了簡要回顧一下使用僅限位置和關(guān)鍵字說明符的函數(shù)簽名,下面是一些進(jìn)一步的示例。省略不定量位置和關(guān)鍵字參數(shù),為簡潔起見,我們只剩下以下語法:

def xxxFuncName(positional_only_parameters, /,
positional_or_keyword_parameters, *,
keyword_only_parameters):
# 函數(shù)體
pass

首先,我們有僅限位置的參數(shù),然后是位置或關(guān)鍵字參數(shù),最后是僅限關(guān)鍵字參數(shù)。

其他一些有效簽名如下:

def xxxFuncName(p1, p2, /, p_or_kw, *, kw):
def xxxFuncName(p1, p2=None, /, p_or_kw=None, *, kw):
def xxxFuncName(p1, p2=None, /, *, kw):
def xxxFuncName(p1, p2=None, /):
def xxxFuncName(p1, p2, /, p_or_kw):
def xxxFuncName(p1, p2, /):

以上均為有效簽名,下列為無效簽名:

def xxxFuncName(p1, p2=None, /, p_or_kw, *, kw):
def xxxFuncName(p1=None, p2, /, p_or_kw=None, *, kw):
def xxxFuncName(p1=None, p2, /):

你可以在官方文檔中閱讀語法規(guī)范:

https://docs.python.org/3/reference/compound_stmts.html#functiondefinitions

提示:在這一點(diǎn)上,要很好的理解與掌握,一個(gè)有用的練習(xí)方法是實(shí)現(xiàn)上述示例簽名中的任何一個(gè),打印出這些參數(shù)的值,就像我們?cè)谇懊娴木毩?xí)中所做的那樣,并以不同的方式傳遞參數(shù)。

8.避免陷阱!可變默認(rèn)值

要注意的一件事是,在Python中,默認(rèn)值是在定義時(shí)創(chuàng)建的;因此,根據(jù)默認(rèn)值的可變性,對(duì)同一函數(shù)的后續(xù)調(diào)用可能會(huì)有不同的行為。讓我們看一個(gè)例子:

# 帶有可變默認(rèn)值參數(shù)函數(shù)
def func(a=[], b={}):
print(a)
print(b)
print('#' * 12)
a.append(len(a)) # 影響a的默認(rèn)值
b[len(a)] = len(a) # 影響b的默認(rèn)值

func()
func()
func()

兩個(gè)參數(shù)都有可變的默認(rèn)值。這意味著,如果執(zhí)行中影響了這些對(duì)象,任何修改都將停留在后續(xù)的函數(shù)調(diào)用中??纯茨闶欠衲芾斫膺@些調(diào)用的輸出:

[]
{}
############
[0]
{1: 1}
############
[0, 1]
{1: 1, 2: 2}
############

是不是很搞事?雖然這種行為一開始看起來很奇怪,但它實(shí)際上是有意義的,而且非常方便——例如,當(dāng)使用“記憶”技術(shù)時(shí),就有了天生之才的傲嬌。更有趣的是,在調(diào)用之間,我們引入了一個(gè)不使用默認(rèn)值的函數(shù),比如:

# 中間調(diào)停者調(diào)用
func()
func(a=[1, 2, 3], b={'B': 1})
func()

運(yùn)行代碼輸出內(nèi)容如下所示:

[]
{}
############
[1, 2, 3]
{'B': 1}
############
[0]
{1: 1}
############

這個(gè)輸出告訴我們,即使使用其他值調(diào)用函數(shù),默認(rèn)值也會(huì)被保留。我想到的一個(gè)問題是,如何每次都獲得一個(gè)新的空值?慣例是這樣的:

# 無陷阱可變?nèi)笔∧J(rèn)值
def func(a=None):
if a is None:
a = []
# 干些使用a的工作 ...

注意,通過使用前面的技術(shù),如果調(diào)用函數(shù)時(shí)沒有傳遞a,我們總是得到一個(gè)全新的空列表。

本文小結(jié)

本文詳細(xì)介紹了函數(shù)的輸入?yún)?shù)分類、示例和調(diào)用,都是圍繞如下主題展開:

位置或關(guān)鍵字參數(shù):同時(shí)允許位置和關(guān)鍵字參數(shù);

可變位置參數(shù):在元組中收集任意數(shù)量的位置參數(shù);

可變關(guān)鍵字參數(shù):在字典中收集任意數(shù)量的關(guān)鍵字參數(shù);

僅限位置參數(shù):只能作為位置參數(shù)傳遞;

?僅限關(guān)鍵字參數(shù):只能作為關(guān)鍵字參數(shù)傳遞。?

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2022-11-06 21:50:59

Python編程函數(shù)定義

2019-02-19 09:29:21

事務(wù)系統(tǒng)模式MySQL

2020-11-09 07:25:20

函數(shù) JavaScript數(shù)據(jù)

2020-06-16 17:10:44

JavaScriptReact開發(fā)

2023-05-10 07:42:26

Java多線程編程

2009-07-27 13:46:27

網(wǎng)絡(luò)參數(shù)切換

2009-11-18 16:58:55

PHP命名規(guī)則

2010-09-07 11:14:56

DB2配置向?qū)?/a>

2023-11-08 08:43:08

calc函數(shù)CSS

2023-09-11 08:30:30

Creator工廠方法

2020-04-13 08:33:39

高并發(fā)秒殺系統(tǒng)

2010-06-12 10:10:55

2010-10-09 16:51:47

2022-10-08 00:03:00

Debug技巧調(diào)試

2022-11-09 07:42:51

Python編程函數(shù)

2023-11-27 18:09:46

Redis內(nèi)存數(shù)據(jù)庫

2025-01-17 10:52:26

定義函數(shù)編程Python

2023-11-06 19:00:17

Python

2024-01-17 06:23:35

SwiftTypeScript定義函數(shù)

2010-09-29 14:48:16

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)