美文网首页
Python笔记:迭代器、生成器、修饰器

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

作者: whytin | 来源:发表于2017-08-09 17:47 被阅读0次

    迭代器(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

    相关文章

      网友评论

          本文标题:Python笔记:迭代器、生成器、修饰器

          本文链接:https://www.haomeiwen.com/subject/cettrxtx.html