1. 程式人生 > >Python筆記:迭代器、生成器、修飾器

Python筆記:迭代器、生成器、修飾器

迭代器(iterators)

迭代器有一個特點,就是每次迭代容器裡的一個數,把容器裡的數迭代完之後就會停止迭代,出現 StopIteration
 異常。可以把迭代器理解為洗髮水,每次擠一點,擠完了就剩下個空瓶,可以丟掉了。使用容器內建函式__iter__()可以直接生成迭代器,使用iter()函式也可以生成迭代器。

>>> nums = [1, 2, 3]      
>>> iter(nums)                           
<...iterator object at ...>
#生成一個迭代器
>>> 
it = iter(nums) >>> next(it) 1 >>> next(it) 2 >>> next(it) 3 >>> next(it) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration

用在for迴圈裡面:

>>>nums=[1,10,100]
>>>it = nums.__iter__()
>>>sum=0
>>>for
i in it: ...: sum=sum+i ...:print sum 111 >>>for i in it: ...: sum=sum+i ...:print sum 0

生成器(generators)

生成器通常由推導式生成,例如:

>>> (i for i in nums)                    
<generator object <genexpr> at 0x...>
>>> list(i for i in nums)
[1, 2, 3]

如果加上中括號就是列表、加上中括號就是字典或者集合:

>>> [i for i in nums]
[1, 2, 3]
>>> {i for i in range(3)}  
set([0, 1, 2])
>>> {i:i**2 for i in range(3)}   
{0: 0, 1: 1, 2: 4}

還有另外一種生成器的表達方式是yield,當next()被呼叫時,就會執行第一個yield。執行完yield語句後,就會停止。看兩個例子就可以理解:

>>> def f():
...   yield 1
...   yield 2
>>> f()                                   
<generator object f at 0x...>
>>> gen = f()
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration
>>> def f():
...   print("-- start --")
...   yield 3
...   print("-- middle --")
...   yield 4
...   print("-- finished --")
>>> gen = f()
>>> next(gen)
-- start --
3
>>> next(gen)
-- middle --
4
>>> next(gen)                            
-- finished --
Traceback (most recent call last):
 ...
StopIteration

裝飾器(decorators)

假如我們想修正(修飾)一個已經寫好的模組,又不讓這個裝飾侵入到原有的模組程式碼中去,這時候就需要用到裝飾器啦。
第一種方法,我們需要寫一個用來裝飾已有模組的裝飾函式:

>>> def simple_decorator(function):
...   print("doing decoration")
...   return function

假如我們想修飾function()這個函式,只需在函式上面加上@修飾器:

>>> @simple_decorator
... def function():
...   print("inside function")
doing decoration
>>> function()
inside function

這個實際的效果相當於:

function = simple_decorator(function) 

將要進行修飾的函式function當作引數傳遞到修飾器simple_decorator中,然後在進行回撥,賦值回原來的function.

我們的修飾器也可以加引數:

>>> def decorator_with_arguments(arg):
...   print("defining the decorator")
...   def _decorator(function):
...       print("doing decoration, %r" % arg)
...       return function
...   return _decorator
>>> @decorator_with_arguments("abc")
... def function():
...   print("inside function")
defining the decorator
doing decoration, 'abc'
>>> function()
inside function

實際上相當於:

function = decorator_with_arguments("abc")(function)

那麼實際上decorator_with_arguments(“abc”)需要返回一個真正的修飾器來修飾function。例子中是返回_decorator這個修飾器。

當含有多個修飾器時,修飾順序是從下向上的:

>>> @decorator_one
... @decorator_two
... def func():
...   pass

就相當於:

func = decorator_one(decorator_two(func))

第二種方法,使用類的方法來修飾函式:

>>> class myDecorator(object):
...   def __init__(self, fn):
...     print "inside myDecorator.__init__()"
...     self.fn = fn
... 
...   def __call__(self):
...     self.fn()
...     print "inside myDecorator.__call__()"
...
>>> @myDecorator
... def aFunction():
...   print "inside aFunction()"
...
print "Finished decorating aFunction()"

>>>aFunction()
... inside myDecorator.__init__()
... Finished decorating aFunction()
... inside aFunction()
... inside myDecorator.__call__()

使用類的修飾器會有兩個成員:
一個是__init__(),這個方法是在我們給某個函式修飾時被呼叫。
一個是__call__(),這個方法是在我們呼叫被修飾函式時被呼叫的。