(一)Python函數
-
數學定義
y = f(x),y是x的函數,x是自變量.y=f(x0,x1,…,xn)
一個x隻能對應一個y,而一個y可以對應多個x
-
Python函數
由若幹語句組成的語句塊,函數名稱,參數清單構成,它是組織代碼的最小單 元
完成一定的功能
-
函數的作用
結構化程式設計對代碼的最近本的封裝,一般按照功能組織一段代碼
封裝的目的為了複用,減少備援代碼
代碼更加簡潔 美觀,可懂易讀
(二)函數定義
def 函數名(參數清單):
函數體(代碼塊)
[return 傳回值]
函數名就是辨別符,命名要求一樣,可以使用字母.數字.下劃線,但不能用數字開頭.
語句塊必須縮進,約定4個空格
Python的函數若沒有return語句,會隐式傳回一個None值
定義中的參數清單稱為形式參數,隻是一種符号表達(辨別符).簡稱形參.
(三)函數調用
函數定義,隻是聲明了一個函數,但他不被執行,需要調用執行
調用的方式,就是函數後加上小括号,如有必要在括号内填上參數
調用時寫的參數是實際參數,是實實在在傳入的值簡稱實參
def add(x,y): #函數的定義
result = x + y # 函數體
return result # 傳回值
out = add(4,5) #函數的調用.可能有傳回值,使用變量接收這個傳回值
print(out) #print函數加上括号也是調用
-
上面代碼解釋
定義一個函數add,及函數名add,接受兩個參數
該函數計算的結果,通過傳回值傳回,需要return語句
調用時,通過函數名add後加2個參數,傳回值可使用變量接收
函數名也是辨別符,傳回值也是值
定義餘姚在調用前,也就是說調用時,已經被定義過了,否則泡NameError異常
函數是可調用對象,callable()
(四)函數參數
函數在定義是要約定好形式參數,調用時也提供足夠的實際參數,一般來說,形參和實參個數要一緻(可變參數除外).
-
傳參方式
1,位置傳參
定義def f(x,y,z),調用使用f(1,3,5),按照參數定義順序傳入實參
2,關鍵字傳參
定義時def f(x,y,z),調用使用 f(x=1,y=3,z=5),使用形參的名字來傳入實參的方式,如果使用了形參的名字,那麼傳參順序就可和定義順序不同
要求位置參數必須在關鍵字參數之前傳入,位置參數是按位置對應的
def f(x,y,z):
pass
f(z=None,y=10,x=[1])
f((1,),z=6,y=4.1)
-
參數預設值
預設值也稱為預設值,可以在函數定義時,為形參增加一個預設值.其作用:
參數的預設值可以在未傳入足夠的實參的時候,對沒有給定的參數指派為預設值
參數非常多的時候,并不需要使用者每次都輸入所有的參數,簡化函數調用
# 定義一個函數login,參數名稱為host,port,username,password
def login(host='127.0.0.1',port='8080',username='wayne',password='Python'):
print('{}:{}@{}/{}'.format(host,port,username,passwd))
login()
login('127.0.0.1',80.'tom','tom')
login('127.0.0.1',username='root')
login('localhost',port=80,password='com')
login(port=80,password='Python',host='www')
-
可變參數
1,可變位置參數
在形參前使用*表示該形參時可變位置參數,可以接受多個實參
它将手機來的實參組織到一個tuple中
def sum(*nums):
sum = 0
for x in nums:
sum += x
return sum
print(sum[1,3,5])
2,可變關鍵字參數
在形參前使用**表示該形參時可變關鍵字參數,可以接受多個關鍵字參數
它将手機來的實參的名曾和值,組織到一個dict中
def showconfig(**kwargs):
for k,v in kwargs.items():
print('{}={}',format(k,v),end=',')
showconfig(host='127.0.0.1',port=8080,username='wayne',passwd='Python')
-
總結
有可變位置參數和可變關鍵字參數
可變位置參數在形參前使用一個星号*
可變關鍵字參數在形參前使用兩個星号**
可變位置參數和可變關鍵字參數都可以收集若幹個實參,可變位置參數收內建形成一個tuple,可變關鍵字參數收集形成一個dict
混合使用參數的時候,普通參數需要放到參數清單前面,可變參數要放到參數清單後面,可變位置參數需要在可變關鍵字參數之前
def fn(x,y,*args,**kwargs):
print(x,y,args,kwargs,sep='\n',end='\n\n')
fn(3,5,7,9,10,a=1,b='abc')
fn(3,5)
fn(3,5,7)
fn(3,5,a=1,b='abc')
fn(x=3,y=8,7,9,a=1,b='abc')
# 錯在位置傳參必須在關鍵字傳參之前
fn(7,9,y=5,x=3,a=1,b='abc')
# 錯在7和9已經按照位置傳參了,x=3,y=5有重複傳參
(五)keyword-only參數
在形參定義時,在一個*星号之後,或一個可變位置參數之後,出現普通參數,就已經不是不同參數了,稱為keywaord-only參數.
def fn(*args,x):
print(x.args,sep='\n',end='\n\n')
fn(3,5)# x沒有參數報錯,3,5被*args接收
fn(3,5,7)# x沒有參數報錯,3,5,7被*args接收
fn(3,5,x=7)
keyword-only參數,言下之意就是這個參數必須采用關鍵字傳參
可以認為,上例中args可變位置參數已經截獲了所有的位置參數,其後的變量x不可能通過位置傳參傳入.
- **kwargs
def fn(**kwargs,x):
print(x,kwargs,sep='\n',end='\n\n')
直接報文法錯誤
可以認為,kwargs會截獲所有關鍵字傳參,就算寫了x=5,x也沒有機會得到這個值,是以這種文法不存在
-
keyword-only參數另一種形式
*星号後所有不同參數都成了keyword-only參數.
def fn(*,x,y):
print(x,y)
fn(x=6,y=7)
fn(y=8,x=9)
(六)參數的混合使用
# 可變位置參數,keyword-only參數,預設值
def fn(*args,x=5)
print(x)
print(args)
fn() #等價于fn(x=5)
fn(5) #args=5 x=5
fn(x=6) #x = 6
fn(1,2,3,x=10) #args=(1,2,3) x=10
#普通參數,可變位置參數.keyword-only參數,預設值
def fn(y,*args,x=5)
print('x={},y={}',format(x,y))
print(args)
fn() # y沒有預設值,報錯
fn(5) # y=5 x=5
fn(5,6) # y=5 args=6 x=5
fn(x=6) #報錯 y沒有指派
fn(1,2,3,x=10) # y=1 args=(2,3) x=10
fn(y=17,2,3,x=10) # 報錯,2,3,沒有綁定形參
fn(1,2,y=3,x=10) #報錯,先将1指派個y,2指派給args,又給y指派3,y有兩個值
# 普通參數,預設值,可變關鍵數參數
def fn(x=5,**kwargs):
print('x={}'.format(x))
print(kwargs)
fn() # x=5
fn(5) # x=5
fn(x=6) # x=6
fn(y=3,x=10) # x=10 {y:3}
fn(3,y=10) # x=3 {y:10}
fn(y=3,z=20) # x=5 {y:3,z:20}
(七)參數規則
參數規則清單參數一般順序時:普通參數,預設參數,可變位置參數,keyword-only參數(可帶預設值),可變關鍵字參數
- 代碼應該易讀易懂,而不是為難别人
- 請按照書寫習慣定義函數參數
def fn(x,y,z=3,*args,m=4,n,**kwargs):
print(x,y,z,m,n)
print(args)
print(kwargs)
def connect(host='localhost',port='3306',user='admin',password='admin',**kwargs):
print(host,port)
print(user,password)
print(kwargs)
connect(db='cmdb')
connect(host='192.168.1.123',db='cmdb')
connect(host='192.168.1.123',db='cmdb',password='mysql')
- 定義最常用參數為普通函數,可不提供預設值,必須由使用者提供.注意這些參數的順序,最常用的先定義
- 将必須使用名稱的才能使用的參數,定義為kwargs-only參數,要求必須使用關鍵字參數
- 如果函數有很多參數,無法逐一定義,可使用可變參數,如果需要知道這些參數的意義,則使用可變關鍵字參數收集
(八)參數解構
- 在給函數提供實參的時候,可以在疊代對下個前使用*或者**來進行結構的解構,提取出其中所有元素作為函數的實參
- 使用*解構成位置傳參
- 使用**解構成關鍵字傳參
- 提取出來的元素數目要和傳參的要求比對
def add(*iterable):
result = 0
for x in iterable:
result += x
return result
add(1, 2, 3)
add(*[1, 2, 3])
add(*range(5))