一姻灶、函數(shù)
1.1 數(shù)學(xué)定義
-
y=f(x)
癌蚁,y
是x
的函數(shù),x
是自變量算行,y=f(x0, x1, ..., xn)
1.2 Python 函數(shù)
- 有若干語句組成的語句塊、函數(shù)名稱苫耸、參數(shù)列表構(gòu)成州邢,它是組織代碼的最小單元
- 完成一定的功能
1.3 函數(shù)的作用
- 結(jié)構(gòu)化編程對(duì)代碼的最基本的封裝,一般按照功能組織一段代碼
- 封裝的目的為了復(fù)用褪子,較少冗余代碼
- 代碼更加簡潔美觀量淌、可讀易懂
1.4 函數(shù)的分類
- 內(nèi)建函數(shù),如
max()
嫌褪、reversed()
等 - 庫函數(shù)呀枢,如
math.ceil()
等 - 自定義函數(shù),使用
def
關(guān)鍵字定義
二笼痛、函數(shù)定義
def 函數(shù)名(參數(shù)列表):
函數(shù)體 (代碼塊)
[return 返回值]
- 函數(shù)名就是標(biāo)識(shí)符裙秋,命名要求一樣
- 語句塊必須縮進(jìn)琅拌,約定 4 個(gè)空格
- Python 的函數(shù)若沒有
return
語句,會(huì)隱式返回一個(gè)None
值 - 定義中的參數(shù)列表稱為 形式參數(shù)摘刑,只是一種符號(hào)表達(dá)(標(biāo)識(shí)符)进宝,簡稱 形參
三、函數(shù)調(diào)用
- 函數(shù)定義枷恕,只是聲明了一個(gè)函數(shù)即彪,它不能被執(zhí)行,需要調(diào)用執(zhí)行
- 調(diào)用的方式活尊,就是 函數(shù)名后加上小括號(hào)隶校,有必要在括號(hào)內(nèi)填寫上參數(shù)
- 調(diào)用時(shí)寫的參數(shù)是 實(shí)際參數(shù),是實(shí)實(shí)在在傳入的值蛹锰,簡稱 實(shí)參
def add(x, y): # 定義函數(shù)
result = x + y # 函數(shù)體
return result # 返回值
out = add(4, 5) # 調(diào)用函數(shù)深胳,可能有返回值,使用變量接收這個(gè)返回值
print(out) # print 函數(shù)加上小括號(hào)也是調(diào)用
- 上面代碼解釋
- 定義一個(gè)函數(shù)
add
铜犬,及函數(shù)名是add
舞终,接受 2 個(gè)參數(shù) - 該函數(shù)計(jì)算的結(jié)果,通過返回值返回癣猾,需要
return
語句 - 調(diào)用時(shí)敛劝,通過函數(shù)名
add
后加 2 個(gè)參數(shù),返回值可使用變量接收 - 函數(shù)名也是標(biāo)識(shí)符纷宇,返回值也是值
- 定義需要在調(diào)用前夸盟,也就是說調(diào)用時(shí),已經(jīng)被定義過了像捶,否則拋
NameError
異常 - 函數(shù)是 可調(diào)用對(duì)象上陕,
callable()
- 定義一個(gè)函數(shù)
四、函數(shù)參數(shù)
函數(shù)在定義時(shí)要約定好形式參數(shù)拓春,調(diào)用時(shí)也提供足夠的實(shí)際參數(shù)释簿,一般來說,形參和實(shí)參個(gè)數(shù)要一致(可變參數(shù)除外)
4.1 位置傳參
- 定義時(shí)
def func(x, y, z)
硼莽,調(diào)用使用func(1, 3, 5)
庶溶,按照參數(shù)定義順序傳入實(shí)參
4.2 關(guān)鍵字傳參
定義時(shí)
def func(x, y, z)
,調(diào)用使用func(x=1, y=3, z=5)
懂鸵,使用形參的名字來傳入實(shí)參的方式偏螺,若使用了形參名字,那么傳參順序就可和定義順序不同要求位置參數(shù)必須在關(guān)鍵字參數(shù)之前 傳入矾瑰,位置參數(shù)是按位置對(duì)應(yīng)的
def func(x, y, z):
pass
func(z = None, y = 10, x = [1])
func((1,), z = 6, y = 4.1)
func(y = 5, z = 6, 2) # 錯(cuò)誤傳參
4.3 參數(shù)缺省值
缺省值也稱為默認(rèn)值砖茸,可在函數(shù)定義時(shí),為形參增加一個(gè)缺省值
- 參數(shù)的默認(rèn)值可在未傳入足夠的實(shí)參的時(shí)候殴穴,對(duì)沒有給定的參數(shù)賦值為默認(rèn)值
- 參數(shù)非常多的時(shí)候凉夯,并不需要每戶每次都輸入所有的參數(shù)货葬,簡化函數(shù)調(diào)用
def add(x = 4, y = 5):
return x + y
測試調(diào)用 add()、add(x = 5)劲够、add(y = 7)震桶、add(6, 10)、add(6, y = 7)征绎、add(x = 5, y = 6)蹲姐、add(y = 5, x = 7)
add(x = 7, 8)、add(y = 8, 4)人柿、add(11, x=20)
能否這樣定義 def add(x, y = 5) 或 def add(x = 4, y)
# 定義一個(gè)函數(shù) login柴墩,參數(shù)名稱為 host、port凫岖、username江咳、password
def login(host='127.0.0.1', port='8080', username='rookie', password='rookie'):
print('{}:{}@{}/{}'.format(host, port, username, password_+))
login()
login('127.0.0.1', 80, 'tom', 'tom')
login('127.0.0.1', username='jerry')
login('localhost', port=80, password='com')
login(port=80, password='http', host='www')
4.4 可變參數(shù)
需求:寫一個(gè)函數(shù),可對(duì)多個(gè)數(shù)累加求和
def sum(iterable):
sum = 0
for x in iterable:
sum += x
return sum
print(sum([1, 3, 5]))
print(sum(range(4)))
上例哥放,傳入可迭代對(duì)象歼指,并累加每一個(gè)元素
也可使用可變參數(shù)完成上面的函數(shù)
def sum(*nums):
sum = 0
for x in nums:
sum += x
return sum
print(sum([1, 3, 5]))
print(sum(1, 2, 3))
可變位置參數(shù)
在形參前使用
*
表示該形參數(shù)可變位置參數(shù),可接收多個(gè)實(shí)參它將收集來的實(shí)參組織到一個(gè)
tuple
中-
可變關(guān)鍵字參數(shù)
- 在形參前使用
**
表示該形參是可變關(guān)鍵字參數(shù)甥雕,可接收多個(gè)關(guān)鍵字參數(shù) - 它將收集來的實(shí)參的名稱和值踩身,組織到一個(gè)
dict
中
- 在形參前使用
def showconfig(**kwargs):
for k,v in kwargs.items():
print('{}={}'.format(k,v),end=', ')
showconfig(host='127.0.0.1', port=8080, username='rookie', password='rookie')
混合使用
def showconfig(username, password, **kwargs)
def showconfig(username, *args, **kwargs)
def showconfig(username, password, **kwargs, *args)
-
總結(jié)
- 有可變位置參數(shù)和可變關(guān)鍵字參數(shù)
- 可變位置參數(shù)在形參前使用一個(gè)星號(hào)
*
- 可變關(guān)鍵字參數(shù)在形參前使用兩個(gè)星號(hào)
**
- 可變位置參數(shù)和可變關(guān)鍵字參數(shù)都可收集若干實(shí)參,可變位置參數(shù)收集形成一個(gè)
tuple
社露,可變關(guān)鍵字參數(shù)收集形成一個(gè)dict
- 混合使用參數(shù)的時(shí)候挟阻,普通參數(shù)需要放到參數(shù)列表前面,可變參數(shù)要放到參數(shù)列表的后面呵哨,可變位置參數(shù)需要在可變關(guān)鍵字參數(shù)之前
使用舉例
def fn(x, y, *args, **kwargs):
print(x, y, args, kwargs, seq='\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')
fn(x=3, y=8, 7, 9, a=1, b='abc')
赁濒,錯(cuò)在位置傳參必須在關(guān)鍵字傳參之前
fn(7, 9, y=5, x=3, a=1, b='abc')
,錯(cuò)在 7
和 9
已經(jīng)按照位置傳參給 x
及 y
孟害,后面 x=3, y=5
傳參重復(fù)
4.5 keyword=only
參數(shù)
先看一段代碼
def fn(*args, x, y, **kwargs):
print(x, y, args, kwargs, seq='\n', end='\n\n')
fn(3, 5)
fn(3, 5, 7)
fn(3, 5, a=1, b='abc')
fn(3, 5, y=6, x=7, a=1, b='abc')
在 Python3 之后,新增了 keyword-only
參數(shù)
keyword-only
參數(shù):在形參定義時(shí)挪拟,在一個(gè) *
之后挨务,或一個(gè)可變位置參數(shù)之后,出現(xiàn)的普通參數(shù)玉组,就已經(jīng)不是普通的參數(shù)了谎柄,被稱為 keyword-only
參數(shù)
def fn(*args, x):
print(x, args, seq='\n', end='\n\n')
fn(3, 5)
fn(3, 5, 7)
fn(3, 5, x=7)
keyword-only
參數(shù),言下之意就是這個(gè)參數(shù)必須采用關(guān)鍵字傳參
可任務(wù)惯雳,上例中朝巫,args
可變位置參數(shù)已經(jīng)截獲了所有位置參數(shù),其后的變量 x
不可能通過位置傳參傳入了
def fn(**kwargs, x):
print(x, kwargs, seq='\n', end='\n\n')
上例中的定義方式石景,不可行劈猿,語法錯(cuò)誤
可認(rèn)為拙吉,kwargs
會(huì)截獲所有關(guān)鍵字傳參,就算寫了 x=5
揪荣,x
也沒有機(jī)會(huì)得到這個(gè)值筷黔,所以這種語法不存在
keyword-only
參數(shù)另一種形式
*
后所有的普通參數(shù)都成了 keyword-only
參數(shù)
def fn(*, x, y):
print(x, y)
fn(x=6, y=7)
fn(y=8, x=9)
4.6 參數(shù)的混合使用
# 可變位置參數(shù)、keyword-only 參數(shù)仗颈、缺省值
def fn(*args, x=5):
print(x)
print(args)
fn() # 等價(jià)于 fn(x=5)
fn(5)
fn(x=6)
fn(1, 2, 3, x=10)
# 普通參數(shù)佛舱、可變位置參數(shù)、keyword-only 參數(shù)挨决、缺省值
def fn(y, *args, x=5):
print('x={}, y={}'.format(x, y))
print(args)
fn() #
fn(5)
fn(5, 6)
fn(x=6) #
fn(1, 2, 3, x=10)
fn(y=17, 2, 3, x=10) #
fn(1, 2, y=3, x=10) #
# 普通參數(shù)请祖、缺省值、可變關(guān)鍵字參數(shù)
def fn(x=5, **kwargs):
print('x={}'.format(x))
print(kwargs)
fn()
fn(5)
fn(x=6)
fn(y=3, x=10)
fn(3, y=10)
fn(y=3, z=20)
4.7 參數(shù)規(guī)則
參數(shù)列表參數(shù)一般順序是:普通參數(shù)脖祈、缺省值參數(shù)损拢、可變位置參數(shù)、keyword-only
參數(shù)(可帶缺省值)撒犀、可變關(guān)鍵字參數(shù)
- 注意:
- 代碼應(yīng)該易讀易懂福压,而不是為難別人
- 請按照書寫習(xí)慣定義函數(shù)參數(shù)
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')
- 定義最常用參數(shù)為普通參數(shù),可不提供缺省值或舞,必須由用戶提供荆姆,注意這些參數(shù)的順序,最常用的先定義
- 將必須使用名稱的才能使用的參數(shù)映凳,定義為
keyword-only
參數(shù)胆筒,要求必須使用關(guān)鍵字傳參 - 若函數(shù)有很多參數(shù),無法逐一定義诈豌,可使用可變參數(shù)仆救,若需要知道這些參數(shù)的意義,則使用可變關(guān)鍵字參數(shù)收集
五矫渔、參數(shù)解構(gòu)
def add(x, y):
print(x, y)
return x + y
add(4, 5)
add((4, 5))
t = 4, 5
add(t[0] + t[1])
add(*t)
add(*(4, 5))
add(*[4, 5])
add(*{4, 5})
add(*range(4, 6))
add(*{'a':10, 'b':11})
add(**{'a':10, 'b':11}) #
add(**{'x':100, 'y':110})
參數(shù)解構(gòu)
- 在給函數(shù)提供實(shí)參的時(shí)候彤蔽,可在可迭代對(duì)象前使用
*
或**
來進(jìn)行結(jié)構(gòu)的解構(gòu),提取出其中所有元素作為函數(shù)的實(shí)參 - 使用
*
解構(gòu)成位置傳參 - 使用
**
解構(gòu)成關(guān)鍵字傳參 - 提取出來的元素?cái)?shù)目要和參數(shù)的要求匹配
def add(*iterable):
result = 0
for x in iterable:
result += x
return
add(1, 2, 3)
add(*[1, 3, 4])
add(*range(5))
六庙洼、練習(xí)
6.1 編寫一個(gè)函數(shù)顿痪,能夠接受至少 2 個(gè)參數(shù),返回最小值和最大值
def getvalues(min, max, *iterable):
for x in iterable:
if min > x:
min = x
if max < x:
max = x
return min, max
def getvalues(x, y, *args):
print(max(x, y, *args))
print(min(x, y, *args))
6.2 完成一個(gè)函數(shù)油够,可以接受輸入的多個(gè)數(shù)蚁袭,每一次都能返回到目前為止的最大值、最小值
def foo():
max_ = None
min_ = None
while True:
i = input(">>>")
nums = i.replace(',', ' ').split()
if nums[0] == 'quit':
break
for x in nums:
n = int(x)
if max_ is None:
max_ = n
min_ = n
if n > max_:
max_ = n
if n < min_:
min_ = n
print(max_, min_)