Python之函數(shù)
-
什么是函數(shù)
- 函數(shù)是組織好的绳瘟,可重復(fù)使用的刺下,用來實現(xiàn)單一或相關(guān)聯(lián)功能的代碼段。
-
為什么要用函數(shù)
- 函數(shù)能提高應(yīng)用的模塊性和代碼的重復(fù)利用率稽荧。
-
如何定義函數(shù)
函數(shù)代碼塊以 def 關(guān)鍵詞開頭橘茉,后接函數(shù)標(biāo)識符名稱和圓括號()姨丈,圓括號之間可以用于定義參數(shù);
函數(shù)內(nèi)容以冒號起始,并且縮進(jìn);
函數(shù)的第一行語句一般使用多行注釋來闡述函數(shù)的作用。
return [表達(dá)式] 結(jié)束函數(shù),選擇性地返回一個值給調(diào)用方。返回值可以是單個值坷檩,也可以是被元組包裹的多個值裸删,不帶表達(dá)式的return相當(dāng)于返回 None。
-
函數(shù)內(nèi)盡量避免使用print();
def func(): ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass
-
函數(shù)的調(diào)用
-
當(dāng)定義一個函數(shù)后践惑,函數(shù)內(nèi)的所有代碼都不會執(zhí)行,只有調(diào)用函數(shù)時函數(shù)才會被執(zhí)行
def func(): ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass func() # 只有調(diào)用函數(shù)的時候,函數(shù)內(nèi)的代碼才會執(zhí)行
-
-
函數(shù)的參數(shù)
-
函數(shù)的參數(shù)分為實參和形參嫁盲,實參是調(diào)用函數(shù)時傳入的參數(shù),形參是定義函數(shù)時定義的參數(shù)
def func(a): # a就是形參 ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass func('實參')
-
-
函數(shù)的實參分為3種:
-
位置實參:安照順序傳值矫限,從左到右,與形參一一對應(yīng)
def func(a, b): # a = 1,b = 2 ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass func(1, 2) # 位置形參安照順序傳值栏豺,從左到右灵奖,與形參一一對應(yīng)
-
關(guān)鍵字實參:按照關(guān)鍵字對形參進(jìn)行傳值
def func(a, b, c): # a = 1, b = 2, c = 3 ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass func(c=3, a=1, b=2) # 按照關(guān)鍵字對形參進(jìn)行傳值
-
混合實參:位置實參與關(guān)鍵實參混合使用尉尾,關(guān)鍵字實參一定要放在位置實參之后
def func(a, b, c, d): # a = 1, b = 2, c = 3, d = 4 ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass func(1, 2, d=4, c=3) # 當(dāng)使用混合參數(shù)時肢藐,關(guān)鍵字實參一定要放在位置實參之后
-
-
函數(shù)的形參分為4種:
位置形參:按照位置從左到右接收實參傳入的對象。
-
默認(rèn)形參:將經(jīng)常使用的參數(shù)吱韭,設(shè)置一個默認(rèn)值吆豹,調(diào)用函數(shù)的時候,可以省略給默認(rèn)形參傳值理盆。
def func(a, b, c=3): # c = 3 就是默認(rèn)形參 ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass func(1, 2) # 默認(rèn)參數(shù)的陷阱 count = 1 def func(a,b=[]): b.append(a) return b ret1 = func(10) print(ret1) # [10] ret2 = func(20) print(ret2) # [10, 20] # 如果函數(shù)中的默認(rèn)參數(shù)是一個可變數(shù)據(jù)類型痘煤,那么無論調(diào)用多少次這個函數(shù),使用的都是同一個內(nèi)存地址的數(shù)據(jù)猿规。 count = 1 def func(a,b=[]): b.append(a) return b ret1 = func(10) ret2 = func(20) print(ret1) # [10, 20] print(ret2) # [10, 20]
僅限關(guān)鍵字形參
-
萬能形參:可以接收任何形式的參數(shù)
def func(*args, **kwargs): ''' 描述一下這個函數(shù)是干什么的 :return: ''' pass func(1, '任意值', c=[2,3], d=4)
萬能形參之所以可以接收任何形式的參數(shù)衷快,奧秘在于變量args前面的 * 和變量kwargs前面的 ** ;
在定義函數(shù)時,args前面的 * 可以聚合傳入的一切位置實參姨俩,將傳入的所有位置實參生成一個元組蘸拔;而kwargs前面的 ** 可以聚合傳入的一切關(guān)鍵字實參环葵,將傳入的所有關(guān)鍵字實參生成一個字典。
def func(*args, **kwargs): ''' 描述一下這個函數(shù)是干什么的 :return: ''' print(args) # args = (1, '任意值') print(kwargs) kwargs = {'c': [2, 3], 'd': 4} func(1, '任意值', c=[2,3], d=4)
在調(diào)用函數(shù)時张遭,使用 * 則會打散位置實參傳入的一切可迭代對象,并生成一個元組;使用 ** 會將字典打散后聚合成一個字典先誉。
def func(*args, **kwargs): ''' 描述一下這個函數(shù)是干什么的 :return: ''' print(args) # (1, '任', '意', '值', 2, 3, 4, 5) print(kwargs) # {'a': 6, 'b': 7} func(1, *'任意值', *[2,3], *(4,5), **{'a':6}, **{'b':7})
形參的順序:位置參數(shù)湿刽,args, 默認(rèn)參數(shù),僅限關(guān)鍵字參數(shù),*kwargs褐耳。
-
函數(shù)的名稱
-
函數(shù)名指向的是函數(shù)的內(nèi)存地址
def func(): print('函數(shù)變量名') print(func) # 輸出結(jié)果: <function func at 0x000001797CDD93A0>
-
函數(shù)名本質(zhì)上就是一個變量
def func1(): print('func1') def func2(): print('func2') func1 = func2 func1() # 輸出結(jié)果:func2
-
函數(shù)名可以作為容器數(shù)據(jù)類型(元組、列表铃芦、字典等)的元素
def func1(): print('func1') def func2(): print('func2') def func3(): print('func3') l = [func1, func2, func3] for i in l: i() ''' 輸出結(jié)果: func1 func2 func3 '''
-
函數(shù)名可以作為函數(shù)的參數(shù)
def func1(): print('func1') def func2(x): x() print('func2') func2(func1) ''' 輸出結(jié)果: func1 func2 '''
-
函數(shù)名可以作為函數(shù)的返回值
def func1(): print('func1') def func2(x): print('func2') return x ret = func2(func1) ret() ''' 輸出結(jié)果: func2 func1 '''
-
-
三元運(yùn)算
-
如果一個函數(shù)中有且僅有一個 if……else 條件判斷語句,那么這個函數(shù)可以簡寫成如下的三元運(yùn)算:
a = 1 b = 2 if a > b: c = a else: c = b # 可以簡寫成: a = 1 b = 2 c = a if a > b else b # 寫比較兩個值大小的函數(shù)刃滓,輸出較大的值 def func(a, b): if a > b: return a else: return b ret = func(1,2) print(ret) # 使用三元運(yùn)算可以寫成如下形式: def func(a, b): return a if a > b else b ret = func(1,2) print(ret)
-
-
lambda(匿名函數(shù))
-
匿名函數(shù)就是一句話函數(shù)仁烹,使用lambda關(guān)鍵字創(chuàng)建匿名函數(shù),函數(shù)冒號前面的是形參咧虎,冒號后面的表達(dá)式有且只能有一個卓缰。匿名函數(shù)自帶return,而return的結(jié)果就是表達(dá)式的計算后的結(jié)果征唬。
# 普通函數(shù) def func(a, b): return a + b func(1,2) # 輸出結(jié)果:3 # 匿名函數(shù) func = lambda a, b: a + b print(func(1,2)) # 輸出結(jié)果:3 # 匿名函數(shù)與三元表達(dá)式結(jié)合 func = lambda a, b: print(a) if a > b else print(b) func(1,2) # 輸出結(jié)果:2
-
-
Python的內(nèi)置函數(shù)
Python將一些常用的功能封裝成了內(nèi)置函數(shù)茁彭,需要直接調(diào)用总寒,避免了重復(fù)造輪子的過程理肺。
Python標(biāo)準(zhǔn)庫中的內(nèi)置函數(shù)(點擊查看)
以下介紹一些常用的內(nèi)置函數(shù):
-
eval()
將字符串內(nèi)的表達(dá)式拿出來運(yùn)行一下,并拿到該表達(dá)式的運(yùn)行結(jié)果妹萨。在網(wǎng)絡(luò)傳輸、用戶輸入和SQL注入時絕對不要使用乎完!有可能會遭到黑客攻擊!s_1 = '1 + 2' s_2 = '{"a":1, "b":2}' print(eval(s_1)) # 3 print(eval(s_2)) # {'a': 1, 'b': 2}
-
exec()
與eval()
相似囱怕,但exec()
用于處理字符串中的代碼流毫别。msg = ''' for i in range(10): print(i) ''' exec(msg) # 會執(zhí)行msg中的代碼
-
min()
:返回給定參數(shù)的最小值,參數(shù)可以為序列岛宦。# 求出dic中最小的值 dic = {'a':1,'b':2,'c':3} result = min(dic,key=lambda value: dic[value]) print(result)
max()
:返回給定參數(shù)的最大值,參數(shù)可以為序列。-
sorted()
:對所有可迭代的對象進(jìn)行排序操作防嗡。# 求出sults_list中的人按照成績從高到低進(jìn)行排序 sults_list = [('a', 72), ('b', 83), ('c', 98), ('d', 92)] result = sorted(sults_list, key=lambda value: value[1], reverse=True) print(result) # [('c', 98), ('d', 92), ('b', 83), ('a', 72)]
-
filter()
:用于過濾序列侠坎,過濾掉不符合條件的元素蚁趁,返回由符合條件元素組成的新列表实胸。# 篩選出列表l中大于5的數(shù)字 l = [2,4,5,7,3,9,6,8] # print([i for i in l if i > 3]) # 通過列表推導(dǎo)式也可以篩選出來 # filter()循環(huán)列表l,將l中的每個元素放到lambda函數(shù)中庐完,var > 3 為True的留下。 result = filter(lambda var: var > 3, l) # 返回的是迭代器 print(list(result)) # [4, 5, 7, 9, 6, 8]
-
map()
:會根據(jù)提供的函數(shù)對指定序列做映射淆党。# 計算列表中各個元素的平方 l = [2,4,5,7,3,9,6,8] result = map(lambda var: var ** 2, l) print(list(result)) # [4, 16, 25, 49, 9, 81, 36, 64]
abs()
:取絕對值all()
:括號中傳入可迭代的對象,在傳入的可迭代對象當(dāng)中的所有值都為Ture讶凉,返回的布爾值才為Ture;如果可迭代的對象為空慕匠,則返回Ture。any()
:括號中傳入可迭代的對象台谊,在傳入的可迭代對象中只要有一個值為Ture譬挚,返回的布爾值就為Ture锅铅;如果可迭代的對象為空减宣,則返回False。bin()
:將十進(jìn)制轉(zhuǎn)換成二進(jìn)制漆腌。oct()
:將十進(jìn)制轉(zhuǎn)換成八進(jìn)制。hex()
:將十進(jìn)制轉(zhuǎn)換成16進(jìn)制闷尿。bool()
:制造布爾值,其中0统舀、None、空為False誉简。-
bytes()
:制造bytes類型res = ‘Hello’.encoding('utf-8') 等同于 res = bytes(‘Hello’,encoding='utf-8')
callable()
:判斷一個對象是否可以調(diào)用chr()
:把數(shù)字按照ascii碼表轉(zhuǎn)成字符。ord()
:把字符按照ascii碼表轉(zhuǎn)換成數(shù)字闷串。dir()
:查看()內(nèi)對象能夠通過.調(diào)用哪些方法。divmod(x,y)
:計算x除以y的商與余enumerate()
:用于將一個可遍歷的數(shù)據(jù)對象(如列表窿克、元組或字符串)組合為一個索引序列,同時列出數(shù)據(jù)和數(shù)據(jù)序號年叮,一般用在 for 循環(huán)當(dāng)中。globals()
:查看全局作用域中的名字與值的綁定關(guān)系一姿。locals()
:查看局部作用域中的名字與值的綁定關(guān)系。hash()
:檢測數(shù)據(jù)類型是可變還是不可變叮叹;可hash的類型相當(dāng)于不可變的類型,不可hash的類型相當(dāng)于可變類型蛉顽。help()
:查看函數(shù)的幫助信息先较。id()
:用于獲取對象的內(nèi)存地址携冤。len()
:返回對象(字符闲勺、列表、元組等)長度或項目個數(shù)菜循。iter()
:相當(dāng)于.iter()next()
: 相當(dāng)于.next()open()
;用于打開一個文件衙耕,創(chuàng)建一個file對象,相關(guān)的方法才可以調(diào)用它進(jìn)行讀寫臭杰。pow()
:pow(x,y,z) 表示x的y次方對z取余.range()
:可創(chuàng)建一個整數(shù)列表谚中,一般用在 for 循環(huán)中。reversed()
:返回一個反轉(zhuǎn)的迭代器宪塔。round()
: 四舍五入磁奖。slice()
:實現(xiàn)切片對象某筐,主要用在切片操作函數(shù)里的參數(shù)傳遞。sum()
:進(jìn)行求和計算.vars()
:如果不傳值等同于locals(),傳值后等同于object.dict-
zip()
:拉鏈函數(shù)南誊,函數(shù)用于將可迭代的對象作為參數(shù),將對象中對應(yīng)的元素打包成一個個元組霉赡,然后返回由這些元組組成的對象,這樣做的好處是節(jié)約了不少的內(nèi)存穴亏≈靥簦可以使用 list() 轉(zhuǎn)換來輸出列表嗓化。如果各個迭代器的元素個數(shù)不一致谬哀,則返回列表長度與最短的對象相同,利用 ***** 號操作符史煎,可以將元組解壓為列表。s = 'ABCDEF' tu = ('a','b','c','d','e') l = [1,2,3,4] obj = zip(s,tu,l) print(obj) # <zip object at 0x00000241044AFD00> print(list(obj)) # [('A', 'a', 1), ('B', 'b', 2), ('C', 'c', 3), ('D', 'd', 4)]
面向?qū)ο罄锏闹攸c內(nèi)置函數(shù):
classmethod()
staticmethod()
property()
delattr()
hasattr()
getattr()
setattr()
isinstance()
issubclass()
object()
super()
注意:凡是有默認(rèn)形參
key=None
的內(nèi)置函數(shù)伦仍,將key賦值后key=函數(shù)名稱
,它會自動將可迭代對象的每一個元素按照順序傳入key的函數(shù)中 -
-
高階函數(shù)
函數(shù)在Python中是第一類對象充蓝,第一類對象的特性有:
-
可以被引用
def bar(): print('form bar') f=bar
-
可以當(dāng)做參數(shù)傳入
def bar(): print('form bar') def wrapper(func): func() wrapper(bar)
-
可以當(dāng)做函數(shù)的返回值
def bar(): print('form bar') def foo(func): return func f=foo(bar) print(f)
-
可以當(dāng)作容器類型的元素
def get(): print('form get') def put(): print('form get') l=[get,put] l[0]() l[1]()
Python中函數(shù)為什么可以嵌套或者調(diào)用喉磁?因為在Python中一切皆對象!
-
-
開放封閉原則
- 對功能的拓展是開放的协怒,對源碼的修改是封閉的。
-
閉包函數(shù)
- 閉包函數(shù)是一種函數(shù)的嵌套孕暇,當(dāng)內(nèi)層函數(shù)引用或使用外層函數(shù)的非全局變量時就會產(chǎn)生閉包赤兴,被引用的外層非全局變量稱之為自由變量隧哮,這個自由變量會與內(nèi)層函數(shù)產(chǎn)生綁定關(guān)系,故而自由變量不會隨著函數(shù)的執(zhí)行完畢消失沮翔。閉包主要用于保證函數(shù)的安全。
-
裝飾器
-
在不改變原函數(shù)代碼采蚀、調(diào)用方式以及返回值的前提下,為其增加新功能榆鼠,這就是裝飾器。裝飾器本質(zhì)是閉包函數(shù)璧眠,裝飾器遵循開放封閉原則。
def func_1(name): ''' 這是一個實現(xiàn)某個功能函數(shù)袁滥,內(nèi)部擁有大量的代碼,使用pass代替 :return: ''' pass time.sleep(1) # 模擬函數(shù)執(zhí)行的時間 print(F'func_1執(zhí)行完畢题翻!參數(shù)為:{name}') return 1 def func_2(name_1,name_2): ''' 這是一個實現(xiàn)某個功能函數(shù)腰鬼,內(nèi)部擁有大量的代碼嵌赠,使用pass代替 :return: ''' pass time.sleep(2) # 模擬函數(shù)執(zhí)行的時間 print(F'func_2執(zhí)行完畢熄赡!,參數(shù)為:{name_1}彼硫,{name_2}') return 2 # 將func_1和func_2加入計算運(yùn)行時間的功能。要求:不改變原函數(shù)代碼以及調(diào)用方式 import time # 導(dǎo)入時間模塊 def omputation_time(var): # 定義一個新功能的函數(shù) ''' 這是一個計算運(yùn)行時間的函數(shù) :param args: :return: ''' # args = func_1 # args = func_2 def inner(*args,**kwargs): # 為了不改變被裝飾函數(shù)的調(diào)用方式拧篮,需要再定義一個內(nèi)部函數(shù) start_time = time.time() ret = var(*args,**kwargs) # 調(diào)用函數(shù)時,*會將傳入的元組打散 end_time = time.time() print(f'函數(shù)執(zhí)行用時:{end_time - start_time}') return ret # 將被裝飾函數(shù)的返回值返回給omputation_time缺虐,確保被裝飾函數(shù)的返回值不變 return inner # 返回inner()的函數(shù)名 @omputation_time # 語法糖會將下面func_1函數(shù)名作為參數(shù)傳入到omputation_time(args)函數(shù)中 def func_1(name): ''' 這是一個實現(xiàn)某個功能函數(shù)礁凡,內(nèi)部擁有大量的代碼高氮,使用pass代替 :return: ''' pass time.sleep(1) # 模擬函數(shù)執(zhí)行的時間 print(F'func_1執(zhí)行完畢!參數(shù)為:{name}') return 1 ret_1 = func_1('parameter') # 調(diào)用函數(shù)傳入?yún)?shù),并獲取返回值 print(ret_1) ''' 執(zhí)行結(jié)果: func_1執(zhí)行完畢腰涧!參數(shù)為:parameter 函數(shù)執(zhí)行用時:1.0006012916564941 1 ''' @omputation_time # 語法糖會將下面func_2函數(shù)名作為參數(shù)傳入到omputation_time(args)函數(shù)中 def func_2(name_1,name_2): ''' 這是一個實現(xiàn)某個功能函數(shù)紊浩,內(nèi)部擁有大量的代碼,使用pass代替 :return: ''' pass time.sleep(2) # 模擬函數(shù)執(zhí)行的時間 print(F'func_2執(zhí)行完畢坊谁!,參數(shù)為:{name_1}口芍,{name_2}') return 2 func_2('parameter_1', 'parameter_2') # 調(diào)用函數(shù)傳入?yún)?shù),并獲取返回值 ''' 執(zhí)行結(jié)果: func_2執(zhí)行完畢雇卷!鬓椭,參數(shù)為:parameter_1关划,parameter_2 函數(shù)執(zhí)行用時:2.0002026557922363 '''
-
裝飾器的標(biāo)準(zhǔn)語法
def wapper(f): # f表示被裝飾的函數(shù)名傳入時的形參 def inner(*args, **kwargs): # 定義函數(shù)階段*args, **kwargs會將被裝飾函數(shù)的參數(shù)聚合 pass # 可以添加任意代碼,完成調(diào)用函數(shù)之前的功能 ret = f(*args, **kwargs) # 調(diào)用函數(shù)階段*args, **kwargs會將被裝飾函數(shù)的參數(shù)打散 pass # 可以添加任意代碼贮折,完成調(diào)用函數(shù)之后的功能 return ret # 返回被裝飾函數(shù)的執(zhí)行后的返回值 return inner()
-