Python三大黑科技 迭代器 生成器 裝飾器

2021-10-24 12:43:57 字數 4566 閱讀 1568

可迭代物件是迭代器、生成器、裝飾器的基礎,可迭代物件簡單來說就是可以用for迴圈遍歷的物件,比如常見的list,set和dict。

對所有的可迭代物件呼叫 dir() 方法時,會發現他們都實現了iter方法。這樣就可以通過 iter(object) 來返回乙個迭代器。

a =

'abcdefg'

b =iter

(a)# 建立迭代器物件

print

(type

(b))

#

可以看到呼叫 iter() 之後,變成了乙個 str_iterator 的物件。會發現增加了 __next__方法。所有實現了 __iter__和__next__兩個方法的物件,都是迭代器。

迭代器是帶狀態的物件,它會記錄當前迭代所在的位置,以方便下次迭代的時候獲取正確的元素。__iter__返回迭代器自身,__next__返回容器中的下乙個值,如果容器中沒有更多元素了,則丟擲stopiteration異常。

# 迭代器

a ='abcdefg'

b =iter

(a)# 建立迭代器物件

print

(type

(b))

while

true

:try

:print

(next

(b))

except stopiteration:

break

python的for迴圈本質上就是通過不斷呼叫next()函式實現的。

生成器就是含有yield關鍵字的函式,是一種用普通語法定義的迭代器。

# 生成器

defgenerator()

:yield

'a'yield

'b'yield

'c'g = generator(

)print

(type

(g))

while

true

:try

:print

(next

(g))

except stopiteration:

break

同樣是通過 def 定義,然後通過 yield 來支援迭代器協議,所以比迭代器寫起來更簡單。

進行函式呼叫的時候,返回乙個生成器物件。在使用 next() 呼叫的時候,遇到 yield 就返回,記錄此時的函式呼叫位置,下次呼叫 next() 時,從斷點處開始。

def

gen(n)

:while n >0:

print

('before'

)yield n

n-=1print

('after'

)gg = gen(3)

while

true

:try

:print

(next

(gg)

)print

('-------------'

)except stopiteration:

break

輸出結果:

before

3-------------

after

before

2-------------

after

before

1-------------

after

你完全可以像使用 iterator 一樣使用 generator ,當然除了定義。定義乙個iterator,你需要分別實現__iter__()方法和__next__()方法,但 generator 只需要乙個小小的yield 。

generator 還有 send() 和 close() 方法,都是只能在next()呼叫之後,生成器出去掛起狀態時才能使用的。

生成器在python中是乙個非常強大的程式設計結構,可以用更少地中間變數寫流式**,此外,相比其它容器物件它更能節省記憶體和cpu,當然它可以用更少的**來實現相似的功能。現在就可以動手重構你的**了,但凡看到類似:

def

something()

: result =

for...

in...

:return result

就可以用生成器函式來代替:

def

iter_something()

:for..

.in..

.:yield x

下面使用普通函式、迭代器、生成器來實現斐波那契數列

def

fab(

max)

: x,y,z =0,

0,1list=[

]while x <

max:

list

y,z = z, x+y+z

x +=

1return

list

iterator方法:
class

fab(

object):

''' iterator to produce fibonacci

'''def__init__

(self,

max)

: self.

max=

max self.x =

0 self.y =

0 self.z =

1def

__iter__

(self)

:return self

def__next__

(self)

:if self.x < self.

max:

r = self.z

self.y,self.z = self.z,self.x + self.y + self.z

self.x +=

1return r

raise stopiteration(

'done'

)

為了節省記憶體,和處於未知輸出的考慮,使用迭代器來改善**,但是迭代器什麼都好,就是寫起來不簡潔。所以用 yield 來改寫第三版。

generator:

def

fab(

max)

: x,y,z =0,

0,1while x <

max:

yield z

y,z = z,x+y+z

x +=

1for x in fab(8)

:print

(x)

裝飾器(decorator)是python中最吸引人的特性,裝飾器本質上還是乙個函式,它可以讓已有的函式不做任何改動的情況下增加功能。

非常適合有切面需求的場景,比如許可權校驗,日誌記錄和效能測試等等。比如你想要執行某個函式前記錄日誌或者記錄時間來統計效能,又不想改動這個函式,就可以通過裝飾器來實現。

1.定義:增強函式或類的功能的乙個函式。

2.作用:增強函式的功能

# 偽**

defdecorator

(func)

:def

(*args,

**kwargs)

:# 可以自定義傳入的引數

# *args:將函式傳入的引數儲存在元組型別的變數args中

# **kwargs:將函式的引數和值儲存在字典型別的變數kwargs中

print

(func.__name__)

# 返回傳入的方法名引數的呼叫

return func(

*args,

**kwargs)

# 返回內層函式的函式名

@decorator

deff()

:pass

f()

3.裝飾器可以傳參,也可以不傳參

# 裝飾器

defdecorator

(func)

:# 巢狀函式

defwrap

(*args,

**kwargs)

:print

('start!'

) func(

*args,

**kwargs)

# 類似於閉包,但是沒有外部環境

print

('end!'

)return wrap

@decorator # 放在需要裝飾的函式前

deff1

(name)

:print

('my name is '

+ name)

f1('hqh'

)# 呼叫方式不變

實際上是對裝飾器的乙個函式封裝,並返回乙個裝飾器。可以把它看成乙個帶引數的閉包。

有了裝飾器,我們就可以剝離出大量與函式功能本身無關的**,增加了**的重用性。

部分理論引用於:

python三大器之迭代器

python中的三大器有迭代器,生成器,裝飾器,本文重點講解下迭代器 迭代器 具備了 next 和 iter 方法的物件 可迭代物件 具備了 iter 方法的物件 1.可迭代物件,可以通過for.in.這類語句迭代讀取一條資料供我們使用的物件稱之為可迭代物件 iterable 可以通過isinsta...

Python三大神器之 迭代器

迭代器定義 迭代器是乙個可以記住遍歷位置的物件 迭代器物件從第乙個元素開始訪問,直到所有的元素被訪問截止 迭代器只會向前,不能向後from collections import iterable class mylist object 這是自定義的列表類 def init self self.lis...

python三大神器之迭代器

可迭代協議 內部含有 iter 方法的值 變數都是可迭代的.可迭代型別和python語言之間的協議.可迭代物件 iterable,內部包含 iter 函式.迭代器 iterator,內部同時包含 iter 和 next 迭代器的特點 1節省記憶體,2.惰性機制,3一次性取值,只能按順序取 可迭代變數...