1. 程式人生 > >python之 可叠代 叠代器 生成器

python之 可叠代 叠代器 生成器

binding strings eem classname mat exec quest lac support

0.

1.總結

(1)

iterable 可叠代(對象) 能力屬性

指一個對象能夠一次返回它的一個成員,for i in a_list 而不需要通過下標完成叠代。
例子包括所有序列類型(list, str, tuple), 以及 dict, file, 還包括定義了 __iter__() 或 __getitem__() 方法的類實例。

iterator 叠代器 具體實現

代表數據流的對象。重復調用叠代器的 next() (python3為 __next__()) 方法將依次返回流中的項。當沒有更多可用數據時,將拋出 StopIteration 異常。

兩者關系 iterator = iter(iterable)

使用可叠代對象時,通常不需要調用 iter() 或親自處理叠代器對象。for 語句會自動創建一個臨時未命名變量,以便在循環期間保存叠代器。

(2) 名叫 generator 生成器 的 iterator 叠代器:通過某種算法“生成”一系列數據,通過 for 循環 或 next() 逐個返回數據。

簡單算法:list comprehension 列表生成式直接返回完整列表,generator expression 生成器表達式返回名叫 generator 生成器 的 iterator 叠代器。

技術分享
In [84]: [i**2 for i in range(10) if i % 2 == 0]
Out[
84]: [0, 4, 16, 36, 64] In [85]: (i**2 for i in range(10) if i % 2 == 0) Out[85]: <generator object <genexpr> at 0x000000000A284CA8> In [86]: [i**2 for i in range(10) if i % 2 == 0] Out[86]: [0, 4, 16, 36, 64] In [87]: gen = (i**2 for i in range(10) if i % 2 == 0) In [88]: gen Out[88]: <generator object <genexpr> at 0x000000000A3AE510> In [
89]: gen.next() Out[89]: 0 In [90]: gen.next() Out[90]: 4 In [91]: for i in gen: ...: print i ...: 16 36 64 In [92]: gen.next() --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-92-b2c61ce5e131> in <module>() ----> 1 gen.next() StopIteration:
View Code

復雜算法:普通函數含有 yield 變成“生成器函數”,調用該函數返回名叫 generator 生成器 的 iterator 叠代器。

每次遇到 yield 將臨時掛起,並保存當前執行狀態(包括局部變量和 try 語句)。當生成器恢復執行時,將從掛起的位置繼續執行,而不是像調用函數一樣每次從頭開始執行。

參考廖雪峰 生成器 斐波拉契數列(Fibonacci),除第一個和第二個數外,任意一個數都可由前兩個數相加得到:

技術分享
In [96]: def fib(max):
    ...:     n, a, b = 0, 0, 1
    ...:     while n < max:
    ...:         print b
    ...:         a, b = b, a + b
    ...:         n = n + 1
    ...:
    ...:

In [97]: fib(6)
1
1
2
3
5
8


In [98]: def fib(max):
    ...:     n, a, b = 0, 0, 1
    ...:     while n < max:
    ...:         yield b    #將 print 修改為 yield
    ...:         a, b = b, a + b
    ...:         n = n + 1
    ...:
    ...:

In [99]: gen = fib(6)

In [100]: gen?
Type:        generator
String form: <generator object fib at 0x000000000A417F30>
Docstring:   <no docstring>

In [101]: gen = fib(6)

In [102]: gen.next()
Out[102]: 1

In [103]: for i in gen:
     ...:     print i
     ...:
1
2
3
5
8

In [104]: gen.next()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-104-b2c61ce5e131> in <module>()
----> 1 gen.next()

StopIteration:
View Code

參考廖雪峰 IBM Python yield 使用淺析

相比如下通過在類中定義 def __iter__(self) 和 def next(self) 來實現可叠代,僅僅把 print b 改為了 yield b,就在保持簡潔性的同時獲得了 iterable 的效果。

技術分享
In [106]: class Fab(object):
     ...:
     ...:    def __init__(self, max):
     ...:        self.max = max
     ...:        self.n, self.a, self.b = 0, 0, 1
     ...:
     ...:    def __iter__(self):
     ...:        return self
     ...:
     ...:    def next(self):
     ...:        if self.n < self.max:
     ...:            r = self.b
     ...:            self.a, self.b = self.b, self.a + self.b
     ...:            self.n = self.n + 1
     ...:            return r
     ...:        raise StopIteration()
     ...:

In [107]: gen = Fab(6)

In [108]: gen
Out[108]: <__main__.Fab at 0xa3cd160>

In [109]: gen?
Type:        Fab
String form: <__main__.Fab object at 0x000000000A3CD160>
Docstring:   <no docstring>

In [110]: gen.next()
Out[110]: 1

In [111]: for i in gen:
     ...:     print i
     ...:
1
2
3
5
8

In [112]: gen.next()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-112-b2c61ce5e131> in <module>()
----> 1 gen.next()

<ipython-input-106-0ae2acae18e3> in next(self)
     14            self.n = self.n + 1
     15            return r
---> 16        raise StopIteration()
     17

StopIteration:

In [113]:
View Code

2.參考資料

廖雪峰 叠代 列表生成式 生成器

廖雪峰 IBM Python yield 使用淺析

完全理解Python叠代對象、叠代器、生成器

Iterables vs. Iterators vs. Generators

3.官網資料

https://docs.python.org/2/glossary.html#term-generator

http://python.usyiyi.cn/documents/python_278/glossary.html

http://python.usyiyi.cn/documents/python_352/glossary.html

sequence 序列

An iterable which supports efficient element access using integer indices via the __getitem__() special method and defines a len()method that returns the length of the sequence.

Some built-in sequence types are list, str, tuple, and unicode.

Note that dict also supports __getitem__() and __len__(), but is considered a mapping rather than a sequence because the lookups use arbitrary immutablekeys rather than integers.

一個可叠代對象,它支持通過 __getitem__() 特殊方法使用整數索引來訪問元素,並定義 len() 方法來返回該序列的長度。

一些內建序列類型包括 list, str, tuple 和 unicode (python3: bytes)。

註意 dict 也支持 __getitem__() 和 len() ,但由於它通過任意 immutable 不可變的 keys 而不是整數來查找,dict 被認為是映射而不是序列。

iterable 可叠代(對象)

An object capable of returning its members one at a time. Examples of iterables include all sequence types (such as list, str, and tuple) and some non-sequence types like dict and file and objects of any classes you define with an __iter__() or __getitem__() method.

Iterables can be used in a for loop and in many other places where a sequence is needed (zip(), map(), …).

When an iterable object is passed as an argument to the built-in function iter(), it returns an iterator for the object. This iterator is good for one pass over the set of values. When using iterables, it is usually not necessary to call iter() or deal with iterator objects yourself. The for statement does that automatically for you, creating a temporary unnamed variable to hold the iterator for the duration of the loop. See also iterator, sequence, and generator.

可叠代(對象)是指一個對象能夠一次返回它的一個成員例子包括所有序列類型(list, str, tuple), 以及 dict, file, 還包括定義了 __iter__() 或 __getitem__() 方法的類實例。

可叠代可以應用在 for 循環,以及需要一個序列的其他場合(zip(), map(), ...)。

#zip([iterable, …])
In [7]: zip([1,2,3],[4,5,6])
Out[7]: [(1, 4), (2, 5), (3, 6)]

#map(function, iterable, …)
In [11]: map(lambda x,y:x+y,[1,2,3],[4,5,6])
Out[11]: [5, 7, 9]

廖雪峰 叠代 :在Python中,叠代是通過for ... in來完成的,而很多語言比如C或者Java,叠代list是通過下標完成的。

當可叠代對象作為參數傳遞給內建函數 iter() 時,將返回對象的叠代器。這個叠代器。。。這個叠代器對於一組值是有利的。

使用可叠代對象時,通常不需要調用 iter() 或親自處理叠代器對象。for 語句會自動創建一個臨時未命名變量,以便在循環期間保存叠代器。

In [33]: iter(abc)
Out[33]: <iterator at 0xa387588>

In [34]: iter([1,2,3])
Out[34]: <listiterator at 0xa387da0>

In [35]: iter((1,2,3))
Out[35]: <tupleiterator at 0xa387fd0>

In [36]: d={a:1,b:2}

In [37]: iter(d)
Out[37]: <dictionary-keyiterator at 0xa33def8>

In [38]: d.items()
Out[38]: [(a, 1), (b, 2)]

In [39]: d.iteritems()
Out[39]: <dictionary-itemiterator at 0x3e96458>

In [40]: d.iterkeys()
Out[40]: <dictionary-keyiterator at 0xa3a24f8>

In [41]: d.itervalues()
Out[41]: <dictionary-valueiterator at 0xa3750e8>

iterator 叠代器

An object representing a stream of data. Repeated calls to the iterator’s next() method return successive items in the stream. When no more data are available a StopIteration exception is raised instead. At this point, the iterator object is exhausted and any further calls to its next() method just raise StopIteration again.

Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted. One notable exception is code which attempts multiple iteration passes.

A container object (such as a list) produces a fresh new iterator each time you pass it to theiter() function or use it in a for loop. Attempting this with an iterator will just return the same exhausted iterator object used in the previous iteration pass, making it appear like an empty container.

More information can be found in Iterator Types.

代表數據流的對象。重復調用叠代器的 next() (python3為 __next__()) 方法將依次返回流中的項。當沒有更多可用數據時,將拋出 StopIteration 異常。此時,叠代器對象被耗盡,並且對其 next() 方法的任何進一步調用都會再次引發 StopIteration。

叠代器需要定義 __iter__() 方法來返回叠代器對象本身,因此每一個叠代器也是可叠代對象,並且可以被用於大多數接受可叠代對象的場合。一個值得註意的例外是嘗試。。。一個值得註意的例外是嘗試多次叠代的代碼。

每次將容器對象(比如 list) 傳遞給 iter() 函數或將其用於 for 循環,都將生成一個全新的叠代器。

https://docs.python.org/2/library/stdtypes.html#typeiter

http://python.usyiyi.cn/documents/python_278/library/stdtypes.html#typeiter

http://python.usyiyi.cn/documents/python_352/library/stdtypes.html#typeiter

5.5. Iterator Types 叠代器

New in version 2.2.

Python supports a concept of iteration over containers. This is implemented using two distinct methods; these are used to allow user-defined classes to support iteration.

Sequences, described below in more detail, always support the iteration methods.

One method needs to be defined for container objects to provide iteration support:

Python支持容器上叠代的概念。這種實現使用了兩種獨特的方法;它們被用於讓用戶定義的類支持叠代。

序列”都支持叠代方法。

容器對象需要定義一個方法以支持叠代:

container.__iter__()

Return an iterator object. The object is required to support the iterator protocol described below. If a container supports different types of iteration, additional methods can be provided to specifically request iterators for those iteration types. (An example of an object supporting multiple forms of iteration would be a tree structure which supports both breadth-first and depth-first traversal.) This method corresponds to the tp_iter slot of the type structure for Python objects in the Python/C API.

返回一個叠代器對象。該對象必須支持如下所述的叠代器協議。如果一個容器支持不同類型的叠代,可以提供額外的方法來返回相應的叠代器。(對象支持多種叠代形式的一個示例是支持廣度和深度優先遍歷的樹結構)。

The iterator objects themselves are required to support the following two methods, which together form the iterator protocol:

叠代器對象本身需要支持以下兩種方法,它們組合在一起形成叠代器協議:

iterator.__iter__()

Return the iterator object itself. This is required to allow both containers and iterators to be used with the for and in statements. This method corresponds to the tp_iter slot of the type structure for Python objects in the Python/C API.

返回叠代器對象本身。它使得容器和叠代器能夠應用於 for 和 in 語句。

iterator.next()

Return the next item from the container. If there are no further items, raise the StopIteration exception. This method corresponds to thetp_iternext slot of the type structure for Python objects in the Python/C API.

從容器中返回下一個元素。如果沒有更多的元素,則引發 StopIteration 異常。

Python defines several iterator objects to support iteration over general and specific sequence types, dictionaries, and other more specialized forms. The specific types are not important beyond their implementation of the iterator protocol.

Python定義了幾個叠代器對象,以支持在通用和特定的序列類型、字典以及其他更多特殊形式上的叠代。相比叠代器協議的實現,具體的類型並不重要。

The intention of the protocol is that once an iterator’s next() method raises StopIteration, it will continue to do so on subsequent calls. Implementations that do not obey this property are deemed broken. (This constraint was added in Python 2.3; in Python 2.2, various iterators are broken according to this rule.)

該協議的意圖是一旦叠代器的 next() 方法引發 StopIteration ,後續調用將繼續這樣的行為。不遵守此性質的實現被認為是有問題的。

5.5.1. Generator Types 生成器  

Python’s generators provide a convenient way to implement the iterator protocol. If a container object’s __iter__() method is implemented as a generator, it will automatically return an iterator object (technically, a generator object) supplying the __iter__() andnext() methods. More information about generators can be found in the documentation for the yield expression.

Python的生成器提供了一種方便的方法來實現叠代器協議。如果容器對象的 __iter__() 方法實現為一個生成器,它將自動返回一個提供 __iter__() 和 next() (python3為 __next__())方法的叠代器對象(從技術上講,是生成器對象)。有關生成器的更多信息可以在yield表達式的文檔中找到。

https://docs.python.org/2/reference/expressions.html#yieldexpr

5.2.10. Yield expressions 通過 yield 定義“生成器函數”,調用時返回一個被稱為“生成器”的“叠代器”,具有 .next() 以及 StopIteration

yield_atom       ::=  “(” yield_expression “)”
yield_expression ::=  “yield” [expression_list]

New in version 2.5.

The yield expression is only used when defining a generator function, and can only be used in the body of a function definition. Using ayield expression in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.

When a generator function is called, it returns an iterator known as a generator. That generator then controls the execution of a generator function. The execution starts when one of the generator’s methods is called. At that time, the execution proceeds to the first yieldexpression, where it is suspended again, returning the value of expression_list to generator’s caller. By suspended we mean that all local state is retained, including the current bindings of local variables, the instruction pointer, and the internal evaluation stack. When the execution is resumed by calling one of the generator’s methods, the function can proceed exactly as if the yield expression was just another external call. The value of the yield expression after resuming depends on the method which resumed the execution.

All of this makes generator functions quite similar to coroutines; they yield multiple times, they have more than one entry point and their execution can be suspended. The only difference is that a generator function cannot control where should the execution continue after it yields; the control is always transferred to the generator’s caller.

yield 表達式只用於定義生成器函數,且只能用於函數的定義體中。在函數定義中使用 yield 表達式就可以充分使得該函數定義創建一個生成器函數而不是普通的函數。

當調用生成器函數時,它返回一個稱為生成器的叠代器。然後該生成器控制生成器函數的執行。當調用生成器的其中一個方法時,執行開始。此時,執行會行進到第一個 yield 表達式,在那裏執行被掛起並返回expression_list的值給生成器的調用者。掛起的意思是保存所有的局部狀態,包括當前局部變量的綁定、指令的指針和內部的計算棧。當通過調用生成器的一個方法來恢復執行時,函數可以準確地繼續執行就好像 yield 表達式只是一個外部的調用。恢復執行後 yield 表達式的值取決於恢復執行的方法。

所有這些使得生成器函數與協程非常類似;它們可以 yield 多次,它們有多個入口點且它們的執行可以掛起。唯一的區別是生成器函數不可以控制 yield 之後執行應該從何處繼續;控制始終被轉讓給生成器的調用者。

5.2.10.1. Generator-iterator methods

This subsection describes the methods of a generator iterator. They can be used to control the execution of a generator function.

該小節講述“生成器叠代器”的方法。它們可用於控制生成器函數的執行。

Note that calling any of the generator methods below when the generator is already executing raises a ValueError exception.

註意當生成器已經在執行時調用下面的任何一個生成器方法都將引發 ValueError 異常?????

generator.next()

Starts the execution of a generator function or resumes it at the last executed yield expression. When a generator function is resumed with a next() method, the current yield expression always evaluates to None. The execution then continues to the next yield expression, where the generator is suspended again, and the value of the expression_list is returned to next()’s caller. If the generator exits without yielding another value, a StopIteration exception is raised.

開始生成器函數的執行或者在最後一次執行的yield表達式處恢復執行。當生成器函數使用next()方法恢復執行時,當前的yield表達式始終None。然後執行繼續行進到下一個yield表達式,在那裏生成器被再次掛起並返回expression_list的值給next()的調用者。如果生成器退出時沒有yield另外一個值,則引發一個StopIteration異常。

generator.send(value)

Resumes the execution and “sends” a value into the generator function. The value argument becomes the result of the current yieldexpression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value. When send() is called to start the generator, it must be called with None as the argument, because there is noyield expression that could receive the value.

恢復執行並“發送”一個值到生成器中。該value參數成為當前yield表達式的結果。send()方法返回生成器yield的下一個值,如果生成器退出時沒有yield另外一個值則引發StopIteration。 當調用send()用於(第一次)開始生成器的執行時,它必須以None作為參數進行調用,因為沒有接受該值的yield表達式。

generator.throw(type[, value[, traceback]])

Raises an exception of type type at the point where generator was paused, and returns the next value yielded by the generator function. If the generator exits without yielding another value, a StopIteration exception is raised. If the generator function does not catch the passed-in exception, or raises a different exception, then that exception propagates to the caller.

在生成器暫停的地方引發一個type類型的異常,並返回生成器函數yield的下一個值。如果生成器在退出時沒有yield一個值,則引發StopIteration異常。如果生成器函數沒有捕獲傳遞進來的異常或者引發一個不同的異常,那麽該異常將傳播到調用者。

generator.close()

Raises a GeneratorExit at the point where the generator function was paused. If the generator function then raises StopIteration (by exiting normally, or due to already being closed) or GeneratorExit (by not catching the exception), close returns to its caller. If the generator yields a value, a RuntimeError is raised. If the generator raises any other exception, it is propagated to the caller. close() does nothing if the generator has already exited due to an exception or normal exit.

在生成器函數暫停的地方引發一個GeneratorExit。如果生成器函數此後引發StopIteration(正常退出或者由於已經正在關閉)或者GeneratorExit(沒有捕獲該異常),close會返回到調用者。如果生成器yield一個值,則引發一個RuntimeError。如果生成器引發其它任何異常,它會被傳播到調用者。如果生成器已經由於異常退出或正常退出,close()不會做任何事情。

Here is a simple example that demonstrates the behavior of generators and generator functions:

這裏有個簡單的例子演示生成器和生成器函數的行為:

>>> def echo(value=None):
...     print "Execution starts when ‘next()‘ is called for the first time."
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception, e:
...                 value = e
...     finally:
...         print "Don‘t forget to clean up when ‘close()‘ is called."
...
>>> generator = echo(1)
>>> print generator.next()
Execution starts when next() is called for the first time.
1
>>> print generator.next()
None
>>> print generator.send(2)
2
>>> generator.throw(TypeError, "spam")
TypeError(spam,)
>>> generator.close()
Dont forget to clean up when close() is called.

https://docs.python.org/2/glossary.html#term-generator

generator 生成器(函數)

A function which returns an iterator. It looks like a normal function except that it contains yield statements for producing a series of values usable in a for-loop or that can be retrieved one at a time with the next() function. Each yield temporarily suspends processing, remembering the location execution state (including local variables and pending try-statements). When the generator resumes, it picks-up where it left-off (in contrast to functions which start fresh on every invocation).

返回一個叠代器 iterator 的函數。它看起來像一個普通函數,除了它包含yield表達式,用於產生一系列在 for 循環中可用的值,或者可以使用 next() 函數一次獲取一個值。

每次遇到 yield 將臨時掛起,並保存當前執行狀態(包括局部變量和 try 語句)。當生成器恢復執行時,將從掛起的位置繼續執行,而不是像調用函數一樣每次從頭開始執行。

通常指生成器函數,但在某些上下文中可以引用生成器叠代器。在預期意義不清楚的情況下,使用完整術語避免歧義。

generator iterator 生成器叠代器

https://docs.python.org/3/glossary.html#term-generator-iterator

generator函數創建的對象。

每個yield暫時掛起處理,記住位置執行狀態(包括局部變量和待處理的try語句)。當生成器叠代器恢復時,它會在其中刪除的位置(與在每次調用時開始的函數相反)。

generator expression 生成器表達式

An expression that returns an iterator. It looks like a normal expression followed by a for expression defining a loop variable, range, and an optional if expression. The combined expression generates values for an enclosing function:

返回叠代器的表達式。它看起來像是一個正常表達式,後面是定義循環變量,範圍和可選的if表達式的for表達式。組合表達式生成包圍函數的值:

In [3]: [i*i for i in range(10)]
Out[3]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

In [4]: (i*i for i in range(10))
Out[4]: <generator object <genexpr> at 0x000000000A284F78>

In [5]: sum(i*i for i in range(10))
Out[5]: 285

https://docs.python.org/2/glossary.html#term-list-comprehension

list comprehension 列表推導式

A compact way to process all or part of the elements in a sequence and return a list with the results. result = ["0x%02x" % x for x inrange(256) if x % 2 == 0] generates a list of strings containing even hex numbers (0x..) in the range from 0 to 255. The if clause is optional. If omitted, all elements in range(256) are processed.

list推導式

一種處理序列中所有或部分元素並返回結果列表的緊湊方法。result = [‘{:#04x}‘.format(x) for x in range(256) if x % 2 == 0] generates a list of strings containing even hex numbers (0x..) in the range from 0 to 255. if子句是可選的。如果省略,則處理range(256)中的所有元素。

python之 可叠代 叠代器 生成器