1杂靶、函數(shù)知識(shí)體系
什么是函數(shù)传货?
在程序中具備某一功能的工具就是函數(shù)
函數(shù)的使用原則:先定義晃跺、后調(diào)用為什么要用函數(shù)?
(1)代碼冗余
(2)程序組織結(jié)構(gòu)不清晰也糊、可讀性差
(3)擴(kuò)展性差函數(shù)的分類:
(1)內(nèi)置函數(shù)
python自帶的
(2)自定義函數(shù)
自己定義的自定義函數(shù)和使用
函數(shù)的定義分為兩個(gè)階段:定義和調(diào)用
函數(shù)定義: 定義只檢測(cè)語(yǔ)法不執(zhí)行代碼
def 函數(shù)名(參數(shù)1炼蹦,參數(shù)2...): //必須
"""
文檔注釋
"""
函數(shù)代碼塊1 //必須
函數(shù)代碼塊2
...
return 值
函數(shù)調(diào)用:開(kāi)始執(zhí)行函數(shù)代碼
函數(shù)名()
- 定義函數(shù)的三種方式
(1)無(wú)參函數(shù)
def func():
print('......')
func()
(2)有參函數(shù)
def func(x,y):
if x > y:
return(x)
else:
return(y)
res=func(1,2)
(3)空函數(shù)
def register():
pass
- 調(diào)用函數(shù)的三種形式
(1)語(yǔ)句模式
def func():
print('......')
func()
(2)表達(dá)式形式
def func(x,y):
if x > y:
return(x)
else:
return(y)
res=func(1,2) * 12
print(res)
(3)函數(shù)的調(diào)用可以當(dāng)作另外一個(gè)函數(shù)的參數(shù)傳入
def func(x,y):
if x > y:
return(x)
else:
return(y)
res=func(func(1,2),3)
print(res)
返回值的特點(diǎn)
(1)返回值沒(méi)有類型限制,也沒(méi)有個(gè)數(shù)限制
(2)return是函數(shù)結(jié)束運(yùn)行的標(biāo)志狸剃,函數(shù)內(nèi)可以有多個(gè)return掐隐,但只要執(zhí)行一次return函數(shù)就立即結(jié)束,并且將return后的值當(dāng)作本次調(diào)用的結(jié)果返回钞馁。函數(shù)的參數(shù)
形參即變量名虑省,實(shí)參即變量值,函數(shù)調(diào)用時(shí)僧凰,將值綁定到變量名上探颈,函數(shù)調(diào)用結(jié)束,解除綁定函數(shù)參數(shù)詳解
(1)形參
位置形參:按照從左至右的順序依次定義的形參
特點(diǎn):必須被傳值默認(rèn)參數(shù):在定義階段允悦,就已經(jīng)為某個(gè)形參賦值,該形參稱之為默認(rèn)形參
特點(diǎn):在定義階段就已經(jīng)有值,意味著調(diào)用階段不用為其傳值
def func(x,y=2):
print(x,y)
func(1)
注意:位置形參與默認(rèn)形參可以混用隙弛,位置形參必須放在默認(rèn)形參的前面
(2)實(shí)參
位置實(shí)參:在調(diào)用階段架馋,按照從左到右的順序依次傳入的值
特點(diǎn):這種傳值方式會(huì)與形參一一對(duì)應(yīng)關(guān)鍵字實(shí)參:在調(diào)用階段,按照key=value的格式傳值
特點(diǎn):可以完全打亂位置全闷,但仍然能為指定的形參傳值
注意:
1叉寂、可以混用位置實(shí)參與關(guān)鍵字實(shí)參,但是同一個(gè)形參只能被賦值一次
2总珠、位置實(shí)參必須在關(guān)鍵字實(shí)參的前面
(3)形參中*與**的用法
- 形參中帶*屏鳍,*會(huì)將溢出的位置實(shí)參存成元組的形式然后賦值其后變量名
def func(x,y,*args):
print(x,y,args)
print(1,2,3,4,5,6)
- 形參中帶**;**會(huì)將溢出的關(guān)鍵字實(shí)參存成字典的格式然后賦值其后變量名
def func(x,y,**kwargs):
print(x,y,kwargs)
print(1,y=2,z=3,m=4,n=5)
(4)實(shí)參中* 與**的用法
- 實(shí)參中帶*局服;先將實(shí)參打散成位置實(shí)參钓瞭,然后再與形參做對(duì)應(yīng)
def func(x,y,z):
print(x,y,z)
func(*[1,2,3])
func(*'llo')
- 實(shí)參中帶**;先將實(shí)參打散成關(guān)鍵字實(shí)參淫奔,然后再與形參做對(duì)應(yīng)
def func(x,y,z):
print(x,y,z)
func(**{'x':1,'z':3,'y':2}) //func(z=3,y=2,x=1)
將一個(gè)函數(shù)的參數(shù)完全轉(zhuǎn)給另一個(gè)函數(shù)
def index(x,y,z)
print(x,y,z)
def wrapper(*args,**kwargs):
index(*args,**kwargs)
#以上兩行意思是將一個(gè)函數(shù)的參數(shù)完全傳給另一個(gè)函數(shù)
wrapper(1,2,3)
2山涡、函數(shù)對(duì)象
函數(shù)對(duì)象:把函數(shù)的內(nèi)存地址當(dāng)作一種變量值去使用,函數(shù)對(duì)象不加()唆迁;如果內(nèi)存地址加()就是在調(diào)用函數(shù)
與變量相同的用法:可以被引用鸭丛、可以當(dāng)作參數(shù)傳遞、返回值可以是函數(shù)唐责、可以被儲(chǔ)存到容器類型(列表鳞溉、字典、元組)
獨(dú)有的用法:加()可以運(yùn)行其內(nèi)部代碼
- 可以被引用
def func1()
print('from func')
func2=func1
func2()
- 可以當(dāng)作參數(shù)傳遞
def func1()
print('from func')
def bar(xxx)
xxx()
bar(func1)
- 返回值可以是函數(shù)
def func1()
print('from func')
def bar()
return func1
f=bar()
f()
- 可以被儲(chǔ)存到容器類型(列表鼠哥、字典熟菲、元組)
def func1()
print('from func')
l=[func1,]
l[0]()
3、函數(shù)嵌套
嵌套調(diào)用:在一個(gè)函數(shù)中調(diào)用了另一個(gè)函數(shù)
嵌套定義:在一個(gè)函數(shù)中定義的一個(gè)函數(shù)肴盏,只能在函數(shù)里面使用科盛,外界不能用
def func1()
print('hello')
def func2()
print('world')
func1()
func2()
----------------------------------------
world
hello
4、名稱空間
名稱空間:就是存儲(chǔ)名字與內(nèi)存地址綁定關(guān)系的空間
4.1 名稱空間的分類:
(1)內(nèi)置名稱空間:存儲(chǔ)解釋器自帶的變量名稱與值的對(duì)應(yīng)關(guān)系(print菜皂、len贞绵、max、min)恍飘;python解釋器啟動(dòng)時(shí)創(chuàng)建內(nèi)置名稱空間榨崩,關(guān)閉解釋器銷毀
(2)全局名稱空間:文件級(jí)別的名稱,只要你的名字定義是頂著最左邊(空格也算)寫的就在全局空間章母,除了內(nèi)置的和函數(shù)內(nèi)的母蛛,都是全局名稱空間;執(zhí)行py文件創(chuàng)建全局名稱空間乳怎,關(guān)閉解釋器銷毀
(3)局部名稱空間:只要在函數(shù)里面就是局部的彩郊;調(diào)用函數(shù)時(shí)創(chuàng)建,函數(shù)執(zhí)行完畢銷毀
名稱空間的加載順序
內(nèi)置的名稱空間--->全局的名稱空間---->局部的查找順序
局部的名稱空間---->全局的名稱空間----->內(nèi)置的名稱空間總結(jié):
1、名字的查找順序是從當(dāng)前位置往外查找
2秫逝、名稱空間的嵌套關(guān)系是在函數(shù)定義階段就固定死的恕出,與調(diào)用位置無(wú)關(guān)。
5违帆、作用域(作用范圍)
域:指的是區(qū)域浙巫,范圍的意思
全局的名稱空間和內(nèi)置的名稱空間,在使用上沒(méi)有什么區(qū)別
局部的和全局的內(nèi)置的就區(qū)別了刷后,局部定義的只能在局部使用
函數(shù)的作用域在定義時(shí)就固定了的畴,與調(diào)用的位置沒(méi)有關(guān)系
- 給三個(gè)空間劃分范圍
全局的和內(nèi)置的可以劃分為同一個(gè)范圍
global 表示的全局范圍 ,就是所謂的全局作用域
局部的單獨(dú)劃分為一個(gè)范圍
local 局部作用域
# 查看全局作用域中的內(nèi)容
print(globals())
# 查看全局作用域中的值
print(dir(globals()["_builtins_"]))
#明確使用函數(shù)外的變量
global age(函數(shù)名)
# nonlocal 明確聲明使用上一層的函數(shù)變量尝胆,如果上一層沒(méi)有丧裁,則找上上層的,但是不能找到全局的變量
nonlocal a(函數(shù)名)
# 查看局部作用域中的內(nèi)容
print(locals())
- 總結(jié):
1班巩、如果是不可變類型渣慕,函數(shù)內(nèi)變量值改變不會(huì)改變?nèi)肿兞浚粢淖冃枰暶鞅Щ牛蝗绻强勺冾愋脱疯耄瘮?shù)內(nèi)變量值改變會(huì)改變?nèi)肿兞?br> 2、函數(shù)內(nèi)變量盡量獨(dú)立抑进,不改變?nèi)肿兞俊?/li>
6强经、閉包函數(shù)
閉包函數(shù)與普通函數(shù)的區(qū)別
(1)定義在另一個(gè)函數(shù)中
(2)在內(nèi)部的函數(shù)中使用了外部的變量(不包含全局的變量)
# 為函數(shù)體傳值的方案一:直接以參數(shù)的形式傳入
def f(x):
print(x)
f(10)
# 為函數(shù)體傳值的方案二:函數(shù)之上傳入,并返回函數(shù)本身寺渗,打包成閉包函數(shù)匿情,并且閉包函數(shù)的調(diào)用賦值給全局變量
def inner():
x=10
def f():
print(x)
return f //在返回這個(gè)內(nèi)部的函數(shù)時(shí),不是單純的返回函數(shù)信殊,還把內(nèi)部函數(shù)中訪問(wèn)到的局部名稱一起打包返回炬称,所以叫做閉包函數(shù)
y=inner()
y()
---------------------------------------------
10
# 第二種傳參方式可以演變成:
def inner(x):
def f():
print(x)
return f
y=inner(11)
y()
----------------------------------------------
11
# _closure_用于訪問(wèn),閉包時(shí)打包的數(shù)據(jù)
print(f._closure_[0].cell_contents)
print(f._closure_[1].cell_contents)
7涡拘、裝飾器
7.1 什么是裝飾器
裝飾器:裝飾器就是一個(gè)用于給其它函數(shù)增加功能的函數(shù)
裝飾器本身可以是任意可調(diào)用對(duì)象
被裝飾對(duì)象本身也可以是任意可調(diào)用對(duì)象
7.2 為什么要用裝飾器
開(kāi)閉原則:對(duì)擴(kuò)展開(kāi)放玲躯,對(duì)修改封閉(可以添加新功能,但是不能修改源代碼和調(diào)用方式)
所以添加新功能鳄乏,但是源代碼不能動(dòng)跷车,調(diào)用方式也不能動(dòng);裝飾器的目的就是在遵循開(kāi)閉原則的基礎(chǔ)上添加新功能
裝飾器 和 閉包函數(shù)的關(guān)系:裝飾器是一種設(shè)計(jì)代碼的套路(在不修改源代碼和調(diào)用方式的情況下增加功能)橱野,要完成裝飾器朽缴,就需要使用閉包函數(shù)
# 裝飾器
import time
def index():
print("開(kāi)始下載xxx.mp4")
time.sleep(2)
print("xxx.mp4 下載完成!")
def outter(func):
def wrapper():
start_time = time.time() //此處可修改水援,添加新功能
func()
end_time = time.time() //此處可修改密强,添加新功能
print("下載耗時(shí):",(end_time - start_time))
return wrapper
index=outter(index) //返回給wrapper內(nèi)存地址茅郎;wrapper內(nèi)存地址中又包括最原始的index內(nèi)存地址
index()
# 裝飾器改進(jìn)
import time
def outter(func):
@wraps(func) //將被裝飾對(duì)象的屬性信息傳給新的裝飾器函數(shù)
def wrapper(*args,**kwargs): //將參數(shù)完全傳給func()
start_time = time.time()
res=func(*args,**kwargs) //完全接受wrapper的參數(shù);并且以變量的形式接收f(shuō)unc()的返回值,也就是被裝飾對(duì)象的返回值
end_time = time.time()
print("下載耗時(shí):",(end_time - start_time))
return res
return wrapper
@outter //語(yǔ)法糖或渤;index=outter(index) 只洒,根據(jù)被裝飾函數(shù)的名字,自動(dòng)調(diào)用裝飾器
def index():
print("開(kāi)始下載xxx.mp4")
time.sleep(2)
print("xxx.mp4 下載完成劳坑!")
return 1234 //被裝飾對(duì)象有返回值
@outter //語(yǔ)法糖;home=outter(home)
def home(name): //被裝飾對(duì)象有參數(shù)
time.sleep(1)
print('welcome %s to home page' %name)
裝飾器模板
from functools import wraps //導(dǎo)入functools模塊成畦,裝飾器wraps
def outter(func):
@wraps(func) //將被裝飾對(duì)象的所有屬性賦值給wrapper
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
@outter
def index():
time.sleep(1)
print('welcome to index page')
return 1234
index()
7.3 多個(gè)裝飾器
多個(gè)裝飾器加載順序:(由被裝飾函數(shù))由下至上
多個(gè)裝飾器執(zhí)行順序:由上至下
加載順序:
執(zhí)行順序:
8距芬、三元表達(dá)式
x if x > y else y //條件成立返回左邊,條件不成立返回右邊
res='ok' if True else 'False' //條件成立執(zhí)行左邊循帐,條件不成立執(zhí)行右邊
9框仔、容器表達(dá)式
9.1 列表生成式
l=[i**2 for i in range(10)] //將for循環(huán)的值按照左邊表達(dá)式直接插入列表
l=[i**2 for i in range(10) if i > 4] //將for循環(huán)的值判斷條件,符合條件的值按照左邊表達(dá)式直接插入列表
sbs=[name.upper() for name in names if name.endswith('sb')] //在列表names里拄养,如果有sb結(jié)尾的將其大寫离斩,插入sbs列表
9.2 字典生成式
res=[i:i**2 for i in range(10) if i > 4]
---------------------------------------------------
{5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
9.3 集合生成式
print({i for i in 'hello'})
----------------------------------------------------
{'l', 'o', 'e', 'h'}
10、匿名函數(shù)
匿名函數(shù)就是指定義了一個(gè)函數(shù)的內(nèi)存地址瘪匿,主要用于臨時(shí)使用一次的場(chǎng)景
(lambda x,y:x+y)(1,2) //x,y為參數(shù)跛梗,沒(méi)有函數(shù)名;冒號(hào)后為代碼塊棋弥,自帶return
print(res)
-------------------------------------------------
3
# 匿名函數(shù)通常和其它函數(shù)配合使用
print(max(salaries,key=lambda k:salaries[k])) //以匿名函數(shù)作為參數(shù)比較大泻顺ァ;key的意思是以什么作為比較的參數(shù)顽染,取最大
# 排序
print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) //以value從大到小排序