第四篇: python函数续
1、函數(shù)的嵌套
函數(shù)的嵌套調(diào)用:在調(diào)用一個(gè)函數(shù)的過(guò)程中,又調(diào)用了其它函數(shù)
示例1:
def bar():print('from nbar')def foo():print('from foo')bar() foo() #執(zhí)行結(jié)果為 C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe C:/Users/Administrator/PycharmProjects/python18/day4/函數(shù)嵌套.py from foo from nbar?
示例2:求函數(shù)所帶四個(gè)參數(shù)的最大值
def max2(x,y):if x > y:return xelse:return ydef max4(a,b,c,d):res1=max2(a,b)res2=max2(res1,c)res3=max2(res2,d)return res3 print(max(1,2,3,-1))#執(zhí)行結(jié)果如下 C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe C:/Users/Administrator/PycharmProjects/python18/day4/函數(shù)嵌套.py 3?
函數(shù)的嵌套定義:在一個(gè)函數(shù)的內(nèi)部,又定義另外一個(gè)函數(shù)
2、名稱空間和作用域
名稱空間:存放名字的地方,準(zhǔn)確的說(shuō)名稱空間是存放名字與變量值綁定關(guān)系的地方名稱空間共有三種名稱空間既:
1、內(nèi)置名稱空間:在python解釋器啟動(dòng)時(shí)產(chǎn)生,存放一些python內(nèi)置的名字
2、全局名稱空間:在執(zhí)行文件時(shí)產(chǎn)生,存放文件級(jí)別定義的名字
3、局部名稱空間:在執(zhí)行文件的過(guò)程中,如果調(diào)用了函數(shù),則會(huì)產(chǎn)生該函數(shù)的局部名稱空間,用來(lái)存放該函數(shù)內(nèi)定義的名字,該名字在函數(shù)調(diào)用時(shí)生效,在函數(shù)調(diào)用結(jié)束后失效
加載順序:內(nèi)置===》全局===》局部
優(yōu)先掌握一:名字的查找順序是:局部==》全局===》內(nèi)置
作用域:作用的范圍
全局作用域:全局存貨,全局有效:globals()
局部作用域:臨時(shí)存活,局部生效:locals() x=11111111111111111111111111111111111111111111# def f1(): # x=1 # y=2 # def f2():pass # # print(locals()) # print(globals()) # # f1() # print(locals() is globals()) # print(locals()) # # print(dir(globals()['__builtins__']))#global nonlocal掌握 # x=1 # def f1(): # global x # x=2 # # f1() # print(x)# l=[] # def f2(): # l.append('f2') # # f2() # print(l)# x=0 # def f1(): # # x=1 # def f2(): # # x=2 # def f3(): # # global x # nonlocal x # x=3 # f3() # # print(x) # f2() # print(x) # f1() # print(x)
優(yōu)先掌握二:作用域關(guān)系,在函數(shù)定義時(shí)就已經(jīng)固定,于調(diào)用位置無(wú)關(guān),在調(diào)用函數(shù)時(shí),必須必須必須回到函數(shù)原來(lái)定義的位置去找作用域關(guān)系
x=1 def f1():def f2():print(x)return f2# func=f1() # print(func) # x=10000000 # func() # x=10000000def foo(func):x=300000000func() #f2() x=10000000000000000000000foo(f1()) # x=10000000000000000000000 # foo(f1())
3、閉包函數(shù)
1. 定義在函數(shù)內(nèi)部的函數(shù)
2. 包含對(duì)外部作用域名字的引用,而不是對(duì)全局作用域名字的引用,那么該內(nèi)部函數(shù)就稱為閉包函數(shù)
?
閉包函數(shù)的應(yīng)用:惰性計(jì)算
import requests #pip3 install requests# def get(url): # return requests.get(url).text # # print(get('https://www.python.org')) # print(get('https://www.python.org')) # print(get('https://www.python.org')) # print(get('https://www.python.org'))# def index(url): # # url='https://www.python.org' # def get(): # # return requests.get(url).text # print(requests.get(url).text) # # return get # # python_web=index('https://www.python.org') # baidu_web=index('https://www.baidu.com')# python_web() # baidu_web()name='egon' def index(url):x=1y=2def wrapper():# x# y# return requests.get(url).textprint(name)return wrapperpython_web=index('https://www.python.org')# print(python_web.__closure__[0].cell_contents) print(python_web.__closure__) # print(python_web.__closure__[0].cell_contents) # print(python_web.__closure__[1].cell_contents) # print(python_web.__closure__[2].cell_contents)?
4、裝飾器
1、 開(kāi)放封閉原則:對(duì)擴(kuò)展是開(kāi)放的,對(duì)修改是封閉
2、 裝飾器:裝飾它人的工具,裝飾器本身可以是任意可調(diào)用對(duì)象,被裝飾的對(duì)象本身也可以是任意可調(diào)用對(duì)象
2.1 裝飾器的遵循的原則:
2.1.1、 不修改被裝飾對(duì)象的源代碼
2.1.2、 不修改被調(diào)用對(duì)象的調(diào)用方式
裝飾器名,必須寫在被裝飾對(duì)象的正上方,并且是單獨(dú)一行
import timedef timmer(func):# func=indexdef wrapper():start=time.time()func()stop=time.time()print('run time is %s' %(stop-start))return wrapper@timmer # index=timmer(index) def index():time.sleep(3)print('welcome to index') @timmer # home=timmer(home) def home():time.sleep(2)print('welcome to home page')index() home()裝飾器補(bǔ)充
#補(bǔ)充一:wraps# import time # from functools import wraps # # def timmer(func): # @wraps(func) # def wrapper(*args,**kwargs): # start=time.time() # res=func(*args,**kwargs) # stop=time.time() # print('run time is %s' %(stop-start)) # return res # return wrapper # # # @timmer # index=timmer(index) # def index(): # '''這是index函數(shù)''' # time.sleep(3) # print('welcome to index') # return 123 # # print(index.__doc__) # # print(help(index))#補(bǔ)充二:一個(gè)函數(shù)頭頂上可以多個(gè)裝飾器 import time from functools import wraps current_user={'user':None}def timmer(func):@wraps(func)def wrapper(*args,**kwargs):start=time.time()res=func(*args,**kwargs)stop=time.time()print('run time is %s' %(stop-start))return resreturn wrapper def auth(auth_type='file'):def deco(func):def wrapper(*args, **kwargs):if auth_type == 'file':if current_user['user']:return func(*args, **kwargs)name = input('name: ').strip()password = input('password: ').strip()with open('db.txt', encoding='utf-8') as f:user_dic = eval(f.read())if name in user_dic and password == user_dic[name]:res = func(*args, **kwargs)current_user['user'] = namereturn reselse:print('user or password error')elif auth_type == 'mysql':print('mysql')elif auth_type == 'ldap':print('ldap')else:print('not valid auth_type')return wrapperreturn deco@timmer #index=timmer(wrapper) @auth() # @deco #index=deco(index) #wrapper def index():'''這是index函數(shù)'''time.sleep(3)print('welcome to index')return 123# print(index.__doc__) # print(help(index))index()
5、生成器
?學(xué)習(xí)生成器之前,我們先來(lái)看看什么是列表生成式
#列表生成式 b = [ i*2 for i in range(10)] print(b)###########打印輸出########### #[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]通過(guò)列表生成式,我們可以直接創(chuàng)建一個(gè)列表。但是,受到內(nèi)存限制,列表容量肯定是有限的。而且,創(chuàng)建一個(gè)包含100萬(wàn)個(gè)元素的列表,不僅占用很大的存儲(chǔ)空間,還需要花費(fèi)很長(zhǎng)時(shí)間,如果我們僅僅需要訪問(wèn)前面幾個(gè)元素,那后面絕大多數(shù)元素占用的空間都白白浪費(fèi)了。所以,如果列表元素可以按照某種算法推算出來(lái),那我們是否可以在循環(huán)的過(guò)程中不斷推算出后續(xù)的元素呢?這樣就不必創(chuàng)建完整的list,從而節(jié)省大量的空間。在Python中,這種調(diào)用時(shí)才會(huì)生成相應(yīng)數(shù)據(jù)的機(jī)制,稱為生成器:generator
要?jiǎng)?chuàng)建一個(gè)generator,有很多種方法,第一種方法很簡(jiǎn)單,只要把一個(gè)列表生成式的[]改成(),就創(chuàng)建了一個(gè)生成器
#生成器 l = [ i*2 for i in range(10)] print(l)g = (i*2 for i in range(10)) print(g)###########打印輸出########### #[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] #<generator object <genexpr> at 0x0064AAE0>print(g) 打印出來(lái)的信息顯示g是一個(gè)生成器,創(chuàng)建l和g的區(qū)別僅在于最外層的[]和(),l是一個(gè)list,而g是一個(gè)generator;我們可以直接打印出list的每一個(gè)元素,但我們?cè)趺创蛴〕鰃enerator的每一個(gè)元素呢?如果要一個(gè)一個(gè)打印出來(lái),可以通過(guò)next()函數(shù)獲得generator的下一個(gè)返回值
#生成器next打印 print(next(g)) #......... 不斷next 打印10次 #.......... print(next(g))###########打印輸出########### #0 #........ #18 #Traceback (most recent call last): # File "<stdin>", line 1, in <module> #StopIteration我們講過(guò),generator保存的是算法,每次調(diào)用next(g),就計(jì)算出g的下一個(gè)元素的值,直到計(jì)算到最后一個(gè)元素,沒(méi)有更多的元素時(shí),拋出StopIteration的錯(cuò)誤。
上面這種不斷調(diào)用next(g)實(shí)在是太變態(tài)了,正確的方法是使用for循環(huán),因?yàn)間enerator也是可迭代對(duì)象,所以,我們創(chuàng)建了一個(gè)generator后,基本上永遠(yuǎn)不會(huì)調(diào)用next(),而是通過(guò)for循環(huán)來(lái)迭代它,并且不需要關(guān)心StopIteration的錯(cuò)誤
#生成器for調(diào)用 g = (i*2 for i in range(10)) #不用擔(dān)心出現(xiàn)StopIteration錯(cuò)誤 for i in g:print(i)###########打印輸出########### # 0 # 2 # 4 # 6 # 8 # 10 # 12 # 14 # 16 # 18generator非常強(qiáng)大。如果推算的算法比較復(fù)雜,用列表生成式轉(zhuǎn)換的生成器無(wú)法去實(shí)現(xiàn)時(shí),我們還可以用函數(shù)來(lái)實(shí)現(xiàn)。比如,著名的斐波拉契數(shù)列(Fibonacci)
#函數(shù)表示斐波拉契數(shù)列 def fib(max):n, a, b = 0, 0, 1while n < max:print(b)a, b = b, a + bn += 1return 'done'fib(5) ###########打印輸出########### # 1 # 1 # 2 # 3 # 5仔細(xì)觀察,可以看出,fib函數(shù)實(shí)際上是定義了斐波那契數(shù)列的推算規(guī)則,可以從第一個(gè)元素開(kāi)始,推算出后續(xù)任意的元素,這種邏輯其實(shí)非常類似generator;也就是說(shuō),上面的函數(shù)和generator僅一步之遙,那我們能不能把上面的函數(shù)變成一個(gè)生成器呢?
#斐波拉契數(shù)列轉(zhuǎn)換為generator def fib(max):n, a, b = 0, 0, 1while n < max:#print(b)yield ba, b = b, a + bn += 1return 'done'print(type(fib(5))) #打印fib(5)的類型 for i in fib(5): #for循環(huán)去調(diào)用print(i) ###########打印輸出########### # <class 'generator'> # 1 # 1 # 2 # 3 # 5要把fib函數(shù)變成generator,只需要把print(b)改為yield b就可以了,這就是定義generator的另一種方法。如果一個(gè)函數(shù)定義中包含yield關(guān)鍵字,那么這個(gè)函數(shù)就不再是一個(gè)普通函數(shù),而是一個(gè)generator
但是用for循環(huán)調(diào)用generator時(shí),會(huì)發(fā)現(xiàn)拿不到generator的return語(yǔ)句的返回值,也就是return的值沒(méi)有打印出來(lái),現(xiàn)在我們來(lái)看看怎么去打印generator的返回值
#獲取generator的返回值 def fib(max):n, a, b = 0, 0, 1while n < max:#print(b)yield ba, b = b, a + bn += 1return 'done'g = fib(5) while True:try:x = next(g)print( x)except StopIteration as e:print(e.value)break ###########打印輸出########### # 1 # 1 # 2 # 3 # 5 # done如果想要拿到返回值,必須捕獲StopIteration錯(cuò)誤,返回值包含在StopIteration的value中,關(guān)于如何捕獲錯(cuò)誤,后面的錯(cuò)誤處理還會(huì)詳細(xì)講解。
還可通過(guò)yield實(shí)現(xiàn)在單線程的情況下實(shí)現(xiàn)并發(fā)運(yùn)算的效果
import time def consumer(name):print("%s 準(zhǔn)備吃包子啦!" %name)while True:baozi = yieldprint("包子[%s]來(lái)了,被[%s]吃了!" %(baozi,name))def producer(name):c = consumer('A')c2 = consumer('B')c.__next__() #c.__next__()等同于next(c)c2.__next__()print("老子開(kāi)始準(zhǔn)備做包子啦!")for i in range(10):time.sleep(1)print("%s做了2個(gè)包子!"%(name))c.send(i)c2.send(i)producer("lzl")
6、迭代器
迭代:是一個(gè)重復(fù)的過(guò)程,每一次重復(fù),都是基于上一次的結(jié)果而來(lái)
# while True: #單純的重復(fù) # print('你瞅啥')# l=['a','b','c','d'] # count=0 # while count < len(l): # print(l[count]) # count+=1dic={'name':'egon','sex':'m',"age":18} #上述按照索引的取值方式,不適于沒(méi)有索引的數(shù)據(jù)類型迭代器:
可迭代對(duì)象iterable:凡是對(duì)象下有__iter__方法:對(duì)象.__iter__,該對(duì)象就是可迭代對(duì)象
迭代器對(duì)象:可迭代對(duì)象執(zhí)行內(nèi)置的__iter__方法,得到的結(jié)果就是迭代器對(duì)象
# dic={'name':'egon','sex':'m',"age":18} # # i=dic.__iter__() # # print(i) #iterator迭代器 # # # i.__next__() #next(i) # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) #StopIteration # # l=['a','b','c','d'] # # i=l.__iter__() # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) #StopIteration不依賴于索引的取值方式
# l=['a','b','c','d'] # dic={'name':'egon','sex':'m',"age":18} # iter_l=iter(l) # iter_dic=iter(dic) # while True: # try: # # print(next(iter_l)) # k=next(iter_dic) # print(k,dic[k]) # except StopIteration: # break什么是迭代器對(duì)象:
1 有__iter__,執(zhí)行得到仍然是迭代本身
2 有__next__
迭代器對(duì)象的優(yōu)點(diǎn)
1:提供了一種統(tǒng)一的(不依賴于索引的)迭代方式
2:迭代器本身,比起其他數(shù)據(jù)類型更省內(nèi)存
迭代器對(duì)象的缺點(diǎn)
1:一次性,只能往后走,不能回退,不如索引取值靈活
2:無(wú)法預(yù)知什么時(shí)候取值結(jié)束,即無(wú)法預(yù)知長(zhǎng)度
?
轉(zhuǎn)載于:https://www.cnblogs.com/junxun/p/7224615.html
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的第四篇: python函数续的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Cuckoo WIndows 安装
- 下一篇: 【Rain in ACStar HDU-