調(diào)用函數(shù)
Python內(nèi)置了許多有用的函數(shù),除了查官方文檔外,也可以在交互式命令窗口通過help(函數(shù)名)來查看該函數(shù)的幫助信息。
定義函數(shù)
- eg:
# -*- coding:utf-8 -*-
def my_abs(x): #定義一個絕對值函數(shù)
if x >= 0:
return x;
else:
return -x;
- 空函數(shù),可用
pass語句 - 參數(shù)檢查,可在調(diào)用函數(shù)時檢查出參數(shù)錯誤,eg:
def my_abs(x): #定義一個絕對值函數(shù)
if not isinstance(x, (int, float)): #判是否為數(shù)字
raise TypeError('bad operand type')
if x >= 0:
return x;
else:
return -x;
- 返回多個值,實質(zhì)上是返回一個tuple,eg:
import math
def move(x, y, step, angle=0):
#根據(jù)坐標,步長與角度,生成新坐標
nx = x + step * math.cos(angle)
ny = y + step * math.sin(angle)
return nx, ny
x, y = move(100, 100, 60, math.pi/6)
print(x, y)
#輸出
151.96152422706632 70.0
- 如果函數(shù)執(zhí)行完畢沒有return語句,則自動return None。
函數(shù)的參數(shù)
默認參數(shù)可以簡化參數(shù)的調(diào)用,但當我們提供部分參數(shù)時若不按順序,需要把參數(shù)名寫上。這有一個重要例子需要仔細理解:
def add_end(L=[]):
L.append('END')
return L
正常調(diào)用時沒有問題,但是當使用默認參數(shù)調(diào)用時,第二次、第三次開始結(jié)果就不對了,那是因為默認參數(shù)L也是一個變量,它指向?qū)ο骩],每次調(diào)用該函數(shù),如果改變L的內(nèi)容,則下次調(diào)用默認參數(shù)的內(nèi)容也隨之改變,以下對其修改:
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
這樣無論調(diào)用多少次也不會出問題,所以在編寫程序時如果可以設計一個像str、None的不變對象,就盡量設計成不變對象。
- 可變參數(shù)
若輸入?yún)?shù)不確定,我們首先可以想到傳進list或tuple,eg:
def calc(numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
這樣調(diào)用時需要將參數(shù)組成list或tuple:
calc([1, 2, 3])
calc((1, 2, 3, 4))
當我們把函數(shù)的參數(shù)改為可變參數(shù):
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
這樣我們就可以calc(1,2,3)的方式來調(diào)用函數(shù),在函數(shù)內(nèi)部,參數(shù)numbers接收到的是一個tuple,但如果這時已經(jīng)有一個list或tuple還可以調(diào)用該函數(shù)嗎,答案是可以的,python允許在list或tuple前加一個*號,把list或tuple的元素變成可變參數(shù)傳進去。
- 關鍵字參數(shù)
關鍵字參數(shù)允許傳入0個或多個含參數(shù)名的參數(shù),這些關鍵字參數(shù)在函數(shù)內(nèi)部自動組裝為一個dict。eg:
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
#例
person('Michael', 30)
name: Michael age: 30 other: {}
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ù)的名字,可用命名關鍵字參數(shù),只接受特定關鍵字參數(shù):
def person(name, age, *, city, job):
print(name, age, city, job)
和關鍵字**kw不同,命名關鍵字需要特殊分隔符*,后面的參數(shù)被視為命名關鍵字參數(shù)。eg:
person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
如果函數(shù)定義中已經(jīng)有一個可變參數(shù),則后面跟著的命名關鍵字參數(shù)就不需要特殊分隔符*了。eg:
def person(name, age, *args, city, job):
print(name, age, args, city, job)
注意,命名關鍵字參數(shù)必須傳入?yún)?shù)名,這與位置參數(shù)不同。命名關鍵字可以有缺省值(默認值)。
- 參數(shù)組合
Python中定義函數(shù),必選參數(shù),默認參數(shù),可變參數(shù),關鍵字參數(shù),命名關鍵字參數(shù),可以組合使用,但順序必須為必選參數(shù)→默認參數(shù)→可變參數(shù)→命名關鍵字參數(shù)→關鍵字參數(shù)
遞歸函數(shù)
最經(jīng)典的例子,求階乘:
def fact(n):
if n==1:
return 1
return n*fact(n-1)
使用遞歸函數(shù)要注意防止棧溢出。解決方法是通過尾遞歸優(yōu)化,它的效果和循環(huán)是一樣的。尾遞歸是指在函數(shù)返回時調(diào)用自身本身,而且return不能包含表達式。接下來我們對上面的函數(shù)進行尾遞歸優(yōu)化: