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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容