日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python的装饰器、迭代器、yield_python装饰器,迭代器,生成器,协程

發布時間:2025/3/12 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python的装饰器、迭代器、yield_python装饰器,迭代器,生成器,协程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

python裝飾器[1]

首先先明白以下兩點

#嵌套函數

defout1():definner1():print(1234)

inner1()#當沒有加入inner時out()不會打印輸出1234,當前層級也就是作用域下必須調用函數才能引用

out1()

#函數作用域

defout2():

a= 'aaa'

definner2():

a= 'bbb'

print(a)

inner2()print(a)

out2()#當相同變量處于不同嵌套函數中,會根據作用函數由內而外查找

裝飾器:本質還是一個函數, 在不改變函數調用方式的情況下 對函數進行額外功能的封裝,裝飾一個函數 轉給他一個其他的功能

裝飾器的目的:裝飾器的原本是用來在項目上線之后,因為已經上線了,大批量改代碼的話很麻煩,由此產生了裝飾器

不能修改被裝飾的函數的源代碼

不能修改被裝飾的函數的調用方式

importtimedefdemo():print("wo shi rainbol")deftime1():

start=time.time()

demo()#給time1函數增加了一個demo的功能

end =time.time()print(end-start)

time1()#這樣方式很low,如果有一個添加n個函數添加此功能會很麻煩

importtimedefdemo():print("wo shi rainbol")defdemo2():print("wo yeshi rainbol")deftime1(fuc):

start=time.time()

fuc()#把之前的demo改成公用的fuc,函數即變量

end =time.time()print(end-start)

time1(demo)#通過調用time1方法,fuc賦值成了demo,再調用demo的方法

time1(demo2)#time1(demo。。)

以上完成了對任意函數改變調用方式進行了功能的封裝,那如何用不改變調用方式的情況下對其進行功能的封裝呢?

importtimedefdemo():print("wo shi rainbol")deftime1(fuc):def inner():#根據之前學過的嵌套函數,增加一層inner方法,把值放入其中

start =time.time()

fuc()

end=time.time()print(end-start)return inner#返回inner方法,但是沒有運行

demo = time1(demo)#time1包含了inner的功能/拿到inner的返回值并且賦值給res,裝飾器的目的是不改變變量名所以這邊仍然用demo變量賦值

demo()#demo通過括號運行inner方法

#下面通過真正的裝飾器可以省去上面的步驟

importtimedeftime1(fuc):#2.time1(demo),這里的fuc相當于形參,其實就是demo

definner():

start=time.time()

fuc()

end=time.time()print(end-start)returninner#3.返回inner函數,但沒有執行哦

@time1#1.python先會整體瀏覽一遍代碼關鍵字的代碼,找到了demo方法上頭有裝飾

# 先調用裝飾器,time1也就是demo = time1(demo),括號中的demo相當于實參

defdemo():print("wo shi rainbol")

# demo = time1(demo) <=====> @time1 去掉@time1在這家這段也是一樣的

demo()#4.現在才執行()執行函數

#簡單裝飾器

importtimedefsimper(fuc):def inner(*args,**kwargs):

start=time.time()

fuc(*args,**kwargs)#增加的方法

end =time.time()print(end -start)returninner

@simper#demo = simper(demo)

def demo(name):#定義一個方法

print(name)#增加一個公用的功能點

demo(1)

#高級裝飾器  當我們再原來裝飾器的業務上再增加一個形參,來判斷我們的業務是否符合指定的狀態,這需要外面再套一層函數

importtimedefharder(type):if type == 1:defout(fuc):def inner(*args,**kwargs):

start=time.time()

fuc(*args,**kwargs)

end=time.time()print(end -start)returninnerreturnoutelif type == 2:pass@harder(1)#返回out函數

defdemo(name):print(name)

demo(1)

python裝飾器[2]

裝飾器與之間的迭代

下面是產品四次提出需求后再不修改調用參數使用裝飾器在修改lose函數來完成我們業務上的需求,原因是上線項目許多接口都調用我們這個類下的參數,再不破壞接口本身情況下使用裝飾器迭代是最佳選擇

importtime#現在有一個需求1.0:在整個功能的基礎上再添加一個減去4.5的操作使得最后結果為0,前提條件是不修改調用參數

defouter(fuc):def inner(*args, **kwargs):

a= fuc(*args, **kwargs) - 4.5

returnareturninner#迭代需求1.1:在整個功能的基礎上再添加一個增加10的操作使得最后結果為10,提前條件是不修改調用參數

defouter2(fuc2):def inner2(*args, **kwargs):

b= fuc2(*args, **kwargs) + 10

returnint(b)returninner2#迭代需求1.2:在整個功能的基礎上再添加一個時間參數判斷lose函數的時間,目前為了模擬添加2秒延遲時間,提前條件是不修改調用參數

defshowtime(fuc):def inner3(*args, **kwargs):

starttime=time.time()

a= fuc(*args, **kwargs)

time.sleep(2)

endtime=time.time()

b= endtime -starttimereturna, breturninner3#迭代需求2.0:目前項目的lose的方法在業務繁忙時會異常中斷,為此接口添加異常處理,提前條件是不修改調用參數

deftryexception(fuc):def tryer(self, *args, **kwargs):try:

res= fuc(self, *args, **kwargs)exceptException as e:

self.lose()return 'ERROR'

returnresreturntryer

'''主程序'''classMyDecorato(object):def __init__(self):pass

defchengxu(self, a, b):

c= a +breturnc

@tryexception#4.最后調用tryexception裝飾器,裝飾器之間調用是從下到上來依次調用

@showtime #3.調用showtime裝飾器

@outer2 #2.調用outer2裝飾器

@outer #1.先調用outer裝飾器

deflose(self, c):#頻繁調用的函數lose

pingjun= c / 2

returnpingjun

d=MyDecorato()

res1= d.chengxu(6, 3)

res2, time=d.lose(res1)print('最后的值:', res2, '時間:', time)

python裝飾器[3]

#wrap函數為functools標準庫中模塊

deftest():'''i am test'''

print('一個簡單的實驗')

test()print(test.__doc__)print(test.__name__)#

#>> 一個簡單的實驗#>> i am test#>> test

print('--------------------------------')defouter(fuc):'''outer is me'''

print('this is outer')def inner(*args,**kwargs):'''inner is me'''

print('this is inner1')

fuc(*args,**kwargs)print('this is inner2')returninner

@outerdeftest():'''i am test'''

print('一個簡單的實驗')

test()print(test.__doc__)print(test.__name__)#>> this is outer#>> this is inner1#>> 一個簡單的實驗#>> this is inner2#>> inner is me#>> inner

print('-----------------------')#如果我們想要得到test里面的數據就要調用一個特定裝飾器來幫我們實現

importfunctoolsdefouter(fuc):'''outer is me'''

print('this is outer')#@functools.wraps(fuc)

def inner(*args,**kwargs):'''inner is me'''

print('this is inner1')

fuc(*args,**kwargs)print('this is inner2')#return inner

return functools.update_wrapper(inner,fuc)#@functools.wraps(fuc)也可以,update_wrapper是調用其內部wrapper

@outerdeftest():'''i am test'''

print('一個簡單的實驗')

test()print(test.__doc__)print(test.__name__)#>> this is outer#>> this is inner1#>> 一個簡單的實驗#>> this is inner2#>>> i am test#>> test

print('------------------')#保持wrapper和test的屬性值一樣,這樣也可以實現同樣的效果

importfunctoolsdefouter(fuc):'''outer is me'''

print('this is outer')def inner(*args,**kwargs):'''inner is me'''

print('this is inner1')

fuc(*args,**kwargs)print('this is inner2')

inner.__doc__ = fuc.__doc__inner.__name__ = fuc.__name__

returninner

@outerdeftest():'''i am test'''

print('一個簡單的實驗')

test()print(test.__doc__)print(test.__name__)

python裝飾器[4]

#通過類中的裝飾器實現,普通方式

classFoo(object):def __init__(self):pass

defdecorator(foo):definner(self):print('before')

foo(self)print('after')returninner

@decoratordeftest(self):print('testing')

foo=Foo()

foo.test()

#通過類中的裝飾器實現,繼承方式

classFoo(object):def __init__(self):pass

defdecorator(self):def inner(*args, **kwargs):print('before')

self(*args, **kwargs)print('after')returninner

@decoratordeftest1(self):print('我被執行了')classFoo2(Foo):

@Foo.decorator#執行被繼承的方法

defdecorator(self):print('執行被繼承的方法開始')

super(Foo2, self).test1()#運行Foo2父類Foo的test1方法

print('執行被繼承的方法結束')

foo=Foo()

foo.test1()print('-----')

foo2=Foo2()

foo2.decorator()

#實例

classTest1(object):defdecorator1(self):def inner(*args, **kwargs):

self(*args, **kwargs)print('n年前添加的附加功能')returninner

@decorator1deftest1(self):print('n年前實現的某個功能')classTest2(Test1):defdecorator2(self):def inner(*args, **kwargs):

self(*args, **kwargs)print('今天添加的附加功能')returninner

@decorator2deftest2(self):

super(Test2, self).test1()print('昨天自己實現的功能')

foo=Test2()

foo.test2()

View Code

#通過類中的裝飾器實現,獲取對象方法的實例屬性defmod_test(cls):#返回修改的類

defdecorator(fun):#返回裝飾函數

defnew_fun(self):print(self.before)print(fun(self))print(self.after)returnnew_fun

cls.test=decorator(cls.test)returncls

@mod_testclassFoo(object):def __init__(self):

self.before= "before"self.after= "after"

deftest(self):return "testing"foo=Foo()

foo.test()

python迭代器

l = [1,2,3,4,5,6]print(l.__iter__()) #iter(l)這兩者是一樣的,都返回了一樣迭代器對象

d =(iter(l))print((next(d)))#返回 1

print((next(d)))#返回 2#所以生成器本身就是迭代器

#for循環本身主要做的三件事:

for i in [1,2,34,5,5]:#1.

iter([1,2,34,5,5])#調用可迭代對象的iter方法返回一個迭代器對象#2.調用迭代器對象的next方法#3.處理Stoplteration

#校驗

from collections importIterator,Iterable#Iterable 迭代器#Iterator 迭代對象

print(isinstance([1334],list))#判斷給對象是否為一個list,返回布爾值

print(isinstance(l,Iterable))#判斷是否是迭代對象,返回布爾值

自定義迭代器

classMytest:def __init__(self, len):

self.index=0

self.len=lendef __iter__(self):returnselfdef __next__(self):if self.index

self.index+= 1

returnself.indexraiseStopIterationfor i in Mytest(20):print(i)#打印1-20,迭代器底層調用,結構復雜

python生成器

用法1:

f = (x for x in range(1000))#使用列表生成式外面套了一層中括號并賦值給f對象

print(f)#此時f打印的就是一個生成器對象 at 0x0000000001DD79E8>#此時需要打印x必須如下方式,生成器就像一位廚師,做出x就是一盤盤菜,每一盤菜必須吃完再吃第二盤,而且不能跳著吃,倒著吃

print(next(f))#調用使用next()比較常見

print(next(f))print(next(f))print(f.__next__())#f.__next__()也是可以的 py2的調用方式是f.next直接調用

print(f.__next__())print(f.__next__())

用法2:

#yield也是生成器中的例子,如果在沒有使用next(),函數根本不會被執行,調用每一次程序會檢測yield如果有,yield包括后面的代碼不會執行,直到下次調用才執行下次的,所以函數中只要有yield就是生成器#yield可以理解成return

deftest(len):print(len,'11')yield 1

print(len,'222')yield 2

print(len,'333')

test('1')#此函數不會被調用

for i in test('1'):#for內置有生成器next,可以對生成器對象一直使用next(n)

print(i,'調用')#打印#1 11#1 調用#1 222#2 調用#1 333#這個就是異步io的原理了,python里面的協程基于yield實現

#生成器的好處:#如果我們寫一個 danger = [x for x in range(9999999999999999999)]#當我們打印danger時我們的電腦會在內存中放置0-n的數據,造成內存不足,死機的情況,生成器的出現會把舊變量替換成新變量,從而不會造成大數據所產成內存泄露的問題

nodanger = (x for x in range(999999999999999999999999))print(next(nodanger))

協程

簡單的說只要能夠完成多任務切換的都是協程,規避io操作是協程體現出的效果

yield是協程最底層的使用方法

#yield的使用

deff():print('jjjj')yield 1

print('gggg')yield

print(f())#創建一個生成器對象,但是函數不會執行

gen=f()#next(gen)#執行生成器對象

gen.send(None)

x= gen.send(10)#next(gen)這兩者是一樣的

print(x)

gevent模塊

#gevent模塊 在gevent中主要模式就是greenlet,它是c擴展的輕量級協程

from greenlet importgreenletdeftest1():print('111')

b.switch()print('333')

b.switch()deftest2():print('222')

a.switch()print('444')

a= greenlet(test1)#創建一個生成器對象

b =greenlet(test2)

a.switch()

#from gevent import monkey#monkey.patch_all()#實時監聽io堵塞,效果顯著,要注意的是這兩句話要放到最上面不然就會報錯,我也不知道為什么

importgeventdeftest3():print('模擬io堵塞1')

gevent.sleep(1)#模擬堵塞時間

print('堵塞消除1')deftest4():print('模擬io堵塞2')

gevent.sleep(2)print( '堵塞消除2')

gevent.joinall([gevent.spawn(test3),gevent.spawn(test4)])#joinall效果是如果兩個方法中其中一個出現io堵塞,會跳到另外一個方法,如果都堵塞都會等著,直到io堵塞消除#優勢:io堵塞的時間取決于io堵塞最長的時間,提升效率

協程實例:

from gevent importmonkey

monkey.patch_all()

#gevent模塊  #基于greenlet封裝,避免多線程切換導致io執行效率降低

importgeventimportrequestsdefrun(name, url):

r=requests.get(url)

open(name+ '.html', 'wb').write(r.content)

url= {'rainbol01': 'https://www.cnblogs.com/RainBol/','rainbol02': 'https://www.cnblogs.com/RainBol/p/9505438.html','rainbol03': 'https://www.cnblogs.com/RainBol/p/10077388.html'}for name, url inurl.items():

g= gevent.spawn(run, name, url) #啟動

g.join() #等待并切換

#阻塞等待分配任務完成后結束#l = []#for i in range(10):#g = gevent.spawn(run,name,url)#l = g.append(g)#g.joinall(l)

版權聲明:本文原創發表于 博客園,作者為?RainBol本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。

總結

以上是生活随笔為你收集整理的python的装饰器、迭代器、yield_python装饰器,迭代器,生成器,协程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。