Python笔记:迭代器、生成器、修饰器

2017-08-09  本文已影响0人  whytin

迭代器(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__(),这个方法是在我们调用被修饰函数时被调用的。

Ref:
http://www.scipy-lectures.org/advanced/advanced_python/index.html#decorators
http://coolshell.cn/articles/11265.html

上一篇下一篇

猜你喜欢

热点阅读