test_generators.py

来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· Python 代码 · 共 1,387 行 · 第 1/3 页

PY
1,387
字号
from __future__ import generatorstutorial_tests = """Let's try a simple generator:    >>> def f():    ...    yield 1    ...    yield 2    >>> for i in f():    ...     print i    1    2    >>> g = f()    >>> g.next()    1    >>> g.next()    2"Falling off the end" stops the generator:    >>> g.next()    Traceback (most recent call last):      File "<stdin>", line 1, in ?      File "<stdin>", line 2, in g    StopIteration"return" also stops the generator:    >>> def f():    ...     yield 1    ...     return    ...     yield 2 # never reached    ...    >>> g = f()    >>> g.next()    1    >>> g.next()    Traceback (most recent call last):      File "<stdin>", line 1, in ?      File "<stdin>", line 3, in f    StopIteration    >>> g.next() # once stopped, can't be resumed    Traceback (most recent call last):      File "<stdin>", line 1, in ?    StopIteration"raise StopIteration" stops the generator too:    >>> def f():    ...     yield 1    ...     raise StopIteration    ...     yield 2 # never reached    ...    >>> g = f()    >>> g.next()    1    >>> g.next()    Traceback (most recent call last):      File "<stdin>", line 1, in ?    StopIteration    >>> g.next()    Traceback (most recent call last):      File "<stdin>", line 1, in ?    StopIterationHowever, they are not exactly equivalent:    >>> def g1():    ...     try:    ...         return    ...     except:    ...         yield 1    ...    >>> list(g1())    []    >>> def g2():    ...     try:    ...         raise StopIteration    ...     except:    ...         yield 42    >>> print list(g2())    [42]This may be surprising at first:    >>> def g3():    ...     try:    ...         return    ...     finally:    ...         yield 1    ...    >>> list(g3())    [1]Let's create an alternate range() function implemented as a generator:    >>> def yrange(n):    ...     for i in range(n):    ...         yield i    ...    >>> list(yrange(5))    [0, 1, 2, 3, 4]Generators always return to the most recent caller:    >>> def creator():    ...     r = yrange(5)    ...     print "creator", r.next()    ...     return r    ...    >>> def caller():    ...     r = creator()    ...     for i in r:    ...             print "caller", i    ...    >>> caller()    creator 0    caller 1    caller 2    caller 3    caller 4Generators can call other generators:    >>> def zrange(n):    ...     for i in yrange(n):    ...         yield i    ...    >>> list(zrange(5))    [0, 1, 2, 3, 4]"""# The examples from PEP 255.pep_tests = """Specification:  Yield    Restriction:  A generator cannot be resumed while it is actively    running:    >>> def g():    ...     i = me.next()    ...     yield i    >>> me = g()    >>> me.next()    Traceback (most recent call last):     ...      File "<string>", line 2, in g    ValueError: generator already executingSpecification: Return    Note that return isn't always equivalent to raising StopIteration:  the    difference lies in how enclosing try/except constructs are treated.    For example,        >>> def f1():        ...     try:        ...         return        ...     except:        ...        yield 1        >>> print list(f1())        []    because, as in any function, return simply exits, but        >>> def f2():        ...     try:        ...         raise StopIteration        ...     except:        ...         yield 42        >>> print list(f2())        [42]    because StopIteration is captured by a bare "except", as is any    exception.Specification: Generators and Exception Propagation    >>> def f():    ...     return 1//0    >>> def g():    ...     yield f()  # the zero division exception propagates    ...     yield 42   # and we'll never get here    >>> k = g()    >>> k.next()    Traceback (most recent call last):      File "<stdin>", line 1, in ?      File "<stdin>", line 2, in g      File "<stdin>", line 2, in f    ZeroDivisionError: integer division or modulo by zero    >>> k.next()  # and the generator cannot be resumed    Traceback (most recent call last):      File "<stdin>", line 1, in ?    StopIteration    >>>Specification: Try/Except/Finally    >>> def f():    ...     try:    ...         yield 1    ...         try:    ...             yield 2    ...             1//0    ...             yield 3  # never get here    ...         except ZeroDivisionError:    ...             yield 4    ...             yield 5    ...             raise    ...         except:    ...             yield 6    ...         yield 7     # the "raise" above stops this    ...     except:    ...         yield 8    ...     yield 9    ...     try:    ...         x = 12    ...     finally:    ...         yield 10    ...     yield 11    >>> print list(f())    [1, 2, 4, 5, 8, 9, 10, 11]    >>>Guido's binary tree example.    >>> # A binary tree class.    >>> class Tree:    ...    ...     def __init__(self, label, left=None, right=None):    ...         self.label = label    ...         self.left = left    ...         self.right = right    ...    ...     def __repr__(self, level=0, indent="    "):    ...         s = level*indent + `self.label`    ...         if self.left:    ...             s = s + "\\n" + self.left.__repr__(level+1, indent)    ...         if self.right:    ...             s = s + "\\n" + self.right.__repr__(level+1, indent)    ...         return s    ...    ...     def __iter__(self):    ...         return inorder(self)    >>> # Create a Tree from a list.    >>> def tree(list):    ...     n = len(list)    ...     if n == 0:    ...         return []    ...     i = n // 2    ...     return Tree(list[i], tree(list[:i]), tree(list[i+1:]))    >>> # Show it off: create a tree.    >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")    >>> # A recursive generator that generates Tree leaves in in-order.    >>> def inorder(t):    ...     if t:    ...         for x in inorder(t.left):    ...             yield x    ...         yield t.label    ...         for x in inorder(t.right):    ...             yield x    >>> # Show it off: create a tree.    ... t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")    ... # Print the nodes of the tree in in-order.    ... for x in t:    ...     print x,    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z    >>> # A non-recursive generator.    >>> def inorder(node):    ...     stack = []    ...     while node:    ...         while node.left:    ...             stack.append(node)    ...             node = node.left    ...         yield node.label    ...         while not node.right:    ...             try:    ...                 node = stack.pop()    ...             except IndexError:    ...                 return    ...             yield node.label    ...         node = node.right    >>> # Exercise the non-recursive generator.    >>> for x in t:    ...     print x,    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"""# Examples from Iterator-List and Python-Dev and c.l.py.email_tests = """The difference between yielding None and returning it.>>> def g():...     for i in range(3):...         yield None...     yield None...     return>>> list(g())[None, None, None, None]Ensure that explicitly raising StopIteration acts like any other exceptionin try/except, not like a return.>>> def g():...     yield 1...     try:...         raise StopIteration...     except:...         yield 2...     yield 3>>> list(g())[1, 2, 3]Next one was posted to c.l.py.>>> def gcomb(x, k):...     "Generate all combinations of k elements from list x."......     if k > len(x):...         return...     if k == 0:...         yield []...     else:...         first, rest = x[0], x[1:]...         # A combination does or doesn't contain first....         # If it does, the remainder is a k-1 comb of rest....         for c in gcomb(rest, k-1):...             c.insert(0, first)...             yield c...         # If it doesn't contain first, it's a k comb of rest....         for c in gcomb(rest, k):...             yield c>>> seq = range(1, 5)>>> for k in range(len(seq) + 2):...     print "%d-combs of %s:" % (k, seq)...     for c in gcomb(seq, k):...         print "   ", c0-combs of [1, 2, 3, 4]:    []1-combs of [1, 2, 3, 4]:    [1]    [2]    [3]    [4]2-combs of [1, 2, 3, 4]:    [1, 2]    [1, 3]    [1, 4]    [2, 3]    [2, 4]    [3, 4]3-combs of [1, 2, 3, 4]:    [1, 2, 3]    [1, 2, 4]    [1, 3, 4]    [2, 3, 4]4-combs of [1, 2, 3, 4]:    [1, 2, 3, 4]5-combs of [1, 2, 3, 4]:From the Iterators list, about the types of these things.>>> def g():...     yield 1...>>> type(g)<type 'function'>>>> i = g()>>> type(i)<type 'generator'>>>> [s for s in dir(i) if not s.startswith('_')]['gi_frame', 'gi_running', 'next']>>> print i.next.__doc__x.next() -> the next value, or raise StopIteration>>> iter(i) is i1>>> import types>>> isinstance(i, types.GeneratorType)1And more, added later.>>> i.gi_running0>>> type(i.gi_frame)<type 'frame'>>>> i.gi_running = 42Traceback (most recent call last):  ...TypeError: readonly attribute>>> def g():...     yield me.gi_running>>> me = g()>>> me.gi_running0>>> me.next()1>>> me.gi_running0A clever union-find implementation from c.l.py, due to David Eppstein.Sent: Friday, June 29, 2001 12:16 PMTo: python-list@python.orgSubject: Re: PEP 255: Simple Generators>>> class disjointSet:...     def __init__(self, name):...         self.name = name...         self.parent = None...         self.generator = self.generate()......     def generate(self):...         while not self.parent:...             yield self...         for x in self.parent.generator:...             yield x......     def find(self):...         return self.generator.next()......     def union(self, parent):...         if self.parent:...             raise ValueError("Sorry, I'm not a root!")...         self.parent = parent......     def __str__(self):...         return self.name>>> names = "ABCDEFGHIJKLM">>> sets = [disjointSet(name) for name in names]>>> roots = sets[:]>>> import random>>> random.seed(42)>>> while 1:...     for s in sets:...         print "%s->%s" % (s, s.find()),...     print...     if len(roots) > 1:...         s1 = random.choice(roots)...         roots.remove(s1)...         s2 = random.choice(roots)...         s1.union(s2)...         print "merged", s1, "into", s2...     else:...         breakA->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->K L->L M->Mmerged D into G

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?