1.定義函數(shù):
def my_abs(x):
if x >= 0:
return x
else:
return -x
沒有return叁怪,默認返回None
2.定義空函數(shù)
def nop():
pass
相當于什么也不做,可以用來做函數(shù)體占位符泳叠,沒有這個,定義空函數(shù)會報錯
3.參數(shù)類型檢查摧冀,和異常錯誤拋出
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
isinstance(x, (int, float))用來判斷類型是否相匹配菜拓。raise 相當于java里面的Throw()
4.返回多個值
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
用這樣的方式接受
x, y = move(100, 100, 60, math.pi / 6)
事實上瓣窄,它并不能返回多個值,知識返回一個tuple(...)
默認參數(shù)纳鼎,相當于java里面的重載函數(shù)
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
調(diào)用形式
s=power(x) #相當于調(diào)用power(x,2)
s=power(x,3)
tip:一是必選參數(shù)在前俺夕,默認參數(shù)在后裳凸,否則Python的解釋器會報錯()
可變參數(shù)
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
調(diào)用形式
calc(1,2,3)
calc(*nums) #nums屬于list或者tuple,直接轉(zhuǎn)變成可變參數(shù)傳入進去
關鍵字參數(shù)
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
調(diào)用形式
person('Adam', 45, gender='M', job='Engineer')
kw會當做為dict來處理
如果要限制關鍵字參數(shù)的名字,就可以用命名關鍵字參數(shù)
def person(name, age, *, city, job):
print(name, age, city, job)
其中*是分界符劝贸,它后面的不變姨谷。那么傳入的參數(shù)也只能是city,job。而不能是否其他參數(shù)
函數(shù)的參數(shù)
閱讀: 502374
定義函數(shù)的時候映九,我們把參數(shù)的名字和位置確定下來梦湘,函數(shù)的接口定義就完成了。對于函數(shù)的調(diào)用者來說件甥,只需要知道如何傳遞正確的參數(shù)捌议,以及函數(shù)將返回什么樣的值就夠了,函數(shù)內(nèi)部的復雜邏輯被封裝起來引有,調(diào)用者無需了解禁灼。
Python的函數(shù)定義非常簡單,但靈活度卻非常大轿曙。除了正常定義的必選參數(shù)外,還可以使用默認參數(shù)僻孝、可變參數(shù)和關鍵字參數(shù)导帝,使得函數(shù)定義出來的接口,不但能處理復雜的參數(shù)穿铆,還可以簡化調(diào)用者的代碼您单。
位置參數(shù)
我們先寫一個計算x2的函數(shù):
def power(x):
return x * x
對于power(x)函數(shù),參數(shù)x就是一個位置參數(shù)荞雏。
當我們調(diào)用power函數(shù)時虐秦,必須傳入有且僅有的一個參數(shù)x:
power(5)
25
power(15)
225
現(xiàn)在,如果我們要計算x3怎么辦凤优?可以再定義一個power3函數(shù)悦陋,但是如果要計算x4、x5……怎么辦筑辨?我們不可能定義無限多個函數(shù)俺驶。
你也許想到了,可以把power(x)修改為power(x, n)棍辕,用來計算xn暮现,說干就干:
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
對于這個修改后的power(x, n)函數(shù),可以計算任意n次方:
power(5, 2)
25
power(5, 3)
125
修改后的power(x, n)函數(shù)有兩個參數(shù):x和n楚昭,這兩個參數(shù)都是位置參數(shù)栖袋,調(diào)用函數(shù)時,傳入的兩個值按照位置順序依次賦給參數(shù)x和n抚太。
默認參數(shù)
新的power(x, n)函數(shù)定義沒有問題塘幅,但是昔案,舊的調(diào)用代碼失敗了,原因是我們增加了一個參數(shù)晌块,導致舊的代碼因為缺少一個參數(shù)而無法正常調(diào)用:
power(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: power() missing 1 required positional argument: 'n'
Python的錯誤信息很明確:調(diào)用函數(shù)power()缺少了一個位置參數(shù)n爱沟。
這個時候,默認參數(shù)就排上用場了匆背。由于我們經(jīng)常計算x2呼伸,所以,完全可以把第二個參數(shù)n的默認值設定為2:
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
這樣钝尸,當我們調(diào)用power(5)時括享,相當于調(diào)用power(5, 2):
power(5)
25
power(5, 2)
25
而對于n > 2的其他情況,就必須明確地傳入n珍促,比如power(5, 3)铃辖。
從上面的例子可以看出,默認參數(shù)可以簡化函數(shù)的調(diào)用猪叙。設置默認參數(shù)時娇斩,有幾點要注意:
一是必選參數(shù)在前,默認參數(shù)在后穴翩,否則Python的解釋器會報錯(思考一下為什么默認參數(shù)不能放在必選參數(shù)前面)犬第;
二是如何設置默認參數(shù)。
當函數(shù)有多個參數(shù)時芒帕,把變化大的參數(shù)放前面歉嗓,變化小的參數(shù)放后面。變化小的參數(shù)就可以作為默認參數(shù)背蟆。
使用默認參數(shù)有什么好處鉴分?最大的好處是能降低調(diào)用函數(shù)的難度。
舉個例子带膀,我們寫個一年級小學生注冊的函數(shù)志珍,需要傳入name和gender兩個參數(shù):
def enroll(name, gender):
print('name:', name)
print('gender:', gender)
這樣,調(diào)用enroll()函數(shù)只需要傳入兩個參數(shù):
enroll('Sarah', 'F')
name: Sarah
gender: F
如果要繼續(xù)傳入年齡垛叨、城市等信息怎么辦碴裙?這樣會使得調(diào)用函數(shù)的復雜度大大增加。
我們可以把年齡和城市設為默認參數(shù):
def enroll(name, gender, age=6, city='Beijing'):
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
這樣点额,大多數(shù)學生注冊時不需要提供年齡和城市舔株,只提供必須的兩個參數(shù):
enroll('Sarah', 'F')
name: Sarah
gender: F
age: 6
city: Beijing
只有與默認參數(shù)不符的學生才需要提供額外的信息:
enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')
可見,默認參數(shù)降低了函數(shù)調(diào)用的難度还棱,而一旦需要更復雜的調(diào)用時载慈,又可以傳遞更多的參數(shù)來實現(xiàn)。無論是簡單調(diào)用還是復雜調(diào)用珍手,函數(shù)只需要定義一個办铡。
有多個默認參數(shù)時辞做,調(diào)用的時候,既可以按順序提供默認參數(shù)寡具,比如調(diào)用enroll('Bob', 'M', 7)秤茅,意思是,除了name童叠,gender這兩個參數(shù)外框喳,最后1個參數(shù)應用在參數(shù)age上,city參數(shù)由于沒有提供厦坛,仍然使用默認值五垮。
也可以不按順序提供部分默認參數(shù)。當不按順序提供部分默認參數(shù)時杜秸,需要把參數(shù)名寫上放仗。比如調(diào)用enroll('Adam', 'M', city='Tianjin'),意思是撬碟,city參數(shù)用傳進去的值诞挨,其他默認參數(shù)繼續(xù)使用默認值。
默認參數(shù)很有用呢蛤,但使用不當亭姥,也會掉坑里。默認參數(shù)有個最大的坑顾稀,演示如下:
先定義一個函數(shù),傳入一個list坝撑,添加一個END再返回:
def add_end(L=[]):
L.append('END')
return L
當你正常調(diào)用時静秆,結(jié)果似乎不錯:
add_end([1, 2, 3])
[1, 2, 3, 'END']
add_end(['x', 'y', 'z'])
['x', 'y', 'z', 'END']
當你使用默認參數(shù)調(diào)用時,一開始結(jié)果也是對的:
add_end()
['END']
但是巡李,再次調(diào)用add_end()時抚笔,結(jié)果就不對了:
add_end()
['END', 'END']
add_end()
['END', 'END', 'END']
很多初學者很疑惑,默認參數(shù)是[]侨拦,但是函數(shù)似乎每次都“記住了”上次添加了'END'后的list殊橙。
原因解釋如下:
Python函數(shù)在定義的時候,默認參數(shù)L的值就被計算出來了狱从,即[]膨蛮,因為默認參數(shù)L也是一個變量,它指向?qū)ο骩]季研,每次調(diào)用該函數(shù)敞葛,如果改變了L的內(nèi)容,則下次調(diào)用時与涡,默認參數(shù)的內(nèi)容就變了惹谐,不再是函數(shù)定義時的[]了持偏。
所以,定義默認參數(shù)要牢記一點:默認參數(shù)必須指向不變對象氨肌!
要修改上面的例子鸿秆,我們可以用None這個不變對象來實現(xiàn):
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
現(xiàn)在,無論調(diào)用多少次怎囚,都不會有問題:
add_end()
['END']
add_end()
['END']
為什么要設計str卿叽、None這樣的不變對象呢?因為不變對象一旦創(chuàng)建桩了,對象內(nèi)部的數(shù)據(jù)就不能修改附帽,這樣就減少了由于修改數(shù)據(jù)導致的錯誤。此外井誉,由于對象不變蕉扮,多任務環(huán)境下同時讀取對象不需要加鎖,同時讀一點問題都沒有颗圣。我們在編寫程序時喳钟,如果可以設計一個不變對象,那就盡量設計成不變對象在岂。
可變參數(shù)
在Python函數(shù)中奔则,還可以定義可變參數(shù)。顧名思義蔽午,可變參數(shù)就是傳入的參數(shù)個數(shù)是可變的易茬,可以是1個、2個到任意個及老,還可以是0個抽莱。
我們以數(shù)學題為例子,給定一組數(shù)字a骄恶,b食铐,c……,請計算a2 + b2 + c2 + ……僧鲁。
要定義出這個函數(shù)虐呻,我們必須確定輸入的參數(shù)。由于參數(shù)個數(shù)不確定寞秃,我們首先想到可以把a斟叼,b,c……作為一個list或tuple傳進來春寿,這樣犁柜,函數(shù)可以定義如下:
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
但是調(diào)用的時候,需要先組裝出一個list或tuple:
calc([1, 2, 3])
14
calc((1, 3, 5, 7))
84
如果利用可變參數(shù)堂淡,調(diào)用函數(shù)的方式可以簡化成這樣:
calc(1, 2, 3)
14
calc(1, 3, 5, 7)
84
所以馋缅,我們把函數(shù)的參數(shù)改為可變參數(shù):
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
定義可變參數(shù)和定義一個list或tuple參數(shù)相比扒腕,僅僅在參數(shù)前面加了一個號。在函數(shù)內(nèi)部萤悴,參數(shù)numbers接收到的是一個tuple瘾腰,因此,函數(shù)代碼完全不變覆履。但是蹋盆,調(diào)用該函數(shù)時,可以傳入任意個參數(shù)硝全,包括0個參數(shù):
calc(1, 2)
5
calc()
0
如果已經(jīng)有一個list或者tuple栖雾,要調(diào)用一個可變參數(shù)怎么辦?可以這樣做:
nums = [1, 2, 3]
calc(nums[0], nums[1], nums[2])
14
這種寫法當然是可行的伟众,問題是太繁瑣析藕,所以Python允許你在list或tuple前面加一個*號,把list或tuple的元素變成可變參數(shù)傳進去:
nums = [1, 2, 3]
calc(*nums)
14
*nums表示把nums這個list的所有元素作為可變參數(shù)傳進去凳厢。這種寫法相當有用账胧,而且很常見。
關鍵字參數(shù)
可變參數(shù)允許你傳入0個或任意個參數(shù)先紫,這些可變參數(shù)在函數(shù)調(diào)用時自動組裝為一個tuple治泥。而關鍵字參數(shù)允許你傳入0個或任意個含參數(shù)名的參數(shù),這些關鍵字參數(shù)在函數(shù)內(nèi)部自動組裝為一個dict遮精。請看示例:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
函數(shù)person除了必選參數(shù)name和age外居夹,還接受關鍵字參數(shù)kw。在調(diào)用該函數(shù)時本冲,可以只傳入必選參數(shù):
person('Michael', 30)
name: Michael age: 30 other: {}
也可以傳入任意個數(shù)的關鍵字參數(shù):
person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
關鍵字參數(shù)有什么用准脂?它可以擴展函數(shù)的功能。比如眼俊,在person函數(shù)里,我們保證能接收到name和age這兩個參數(shù)粟关,但是疮胖,如果調(diào)用者愿意提供更多的參數(shù),我們也能收到闷板。試想你正在做一個用戶注冊的功能澎灸,除了用戶名和年齡是必填項外,其他都是可選項遮晚,利用關鍵字參數(shù)來定義這個函數(shù)就能滿足注冊的需求性昭。
和可變參數(shù)類似,也可以先組裝出一個dict县遣,然后糜颠,把該dict轉(zhuǎn)換為關鍵字參數(shù)傳進去:
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, city=extra['city'], job=extra['job'])
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
當然汹族,上面復雜的調(diào)用可以用簡化的寫法:
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
extra表示把extra這個dict的所有key-value用關鍵字參數(shù)傳入到函數(shù)的kw參數(shù),kw將獲得一個dict其兴,注意kw獲得的dict是extra的一份拷貝顶瞒,對kw的改動不會影響到函數(shù)外的extra。
命名關鍵字參數(shù)
對于關鍵字參數(shù)元旬,函數(shù)的調(diào)用者可以傳入任意不受限制的關鍵字參數(shù)榴徐。至于到底傳入了哪些,就需要在函數(shù)內(nèi)部通過kw檢查匀归。
仍以person()函數(shù)為例坑资,我們希望檢查是否有city和job參數(shù):
def person(name, age, **kw):
if 'city' in kw:
# 有city參數(shù)
pass
if 'job' in kw:
# 有job參數(shù)
pass
print('name:', name, 'age:', age, 'other:', kw)
但是調(diào)用者仍可以傳入不受限制的關鍵字參數(shù):
person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)
如果要限制關鍵字參數(shù)的名字,就可以用命名關鍵字參數(shù)穆端,例如袱贮,只接收city和job作為關鍵字參數(shù)。這種方式定義的函數(shù)如下:
def person(name, age, , city, job):
print(name, age, city, job)
和關鍵字參數(shù)kw不同徙赢,命名關鍵字參數(shù)需要一個特殊分隔符字柠,*后面的參數(shù)被視為命名關鍵字參數(shù)。
調(diào)用方式如下:
person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
如果函數(shù)定義中已經(jīng)有了一個可變參數(shù)狡赐,后面跟著的命名關鍵字參數(shù)就不再需要一個特殊分隔符了窑业;
如果缺少,Python解釋器將無法識別位置參數(shù)和命名關鍵字參數(shù):
幾種參數(shù)組合到一起枕屉,一定滿足如下順序
·``` pyton