mirror of
https://github.com/python/cpython.git
synced 2025-12-05 00:52:25 +00:00
New std test for generators, initially populated with doctests NeilS put
together.
This commit is contained in:
parent
bfdf4ecad0
commit
1def351b45
1 changed files with 139 additions and 0 deletions
139
Lib/test/test_generators.py
Normal file
139
Lib/test/test_generators.py
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
simple_tests = """
|
||||||
|
Let's try a simple generator:
|
||||||
|
|
||||||
|
>>> def f():
|
||||||
|
... yield 1
|
||||||
|
... yield 2
|
||||||
|
|
||||||
|
>>> g = f()
|
||||||
|
>>> g.next()
|
||||||
|
1
|
||||||
|
>>> g.next()
|
||||||
|
2
|
||||||
|
>>> g.next()
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in ?
|
||||||
|
File "<stdin>", line 2, in g
|
||||||
|
StopIteration
|
||||||
|
|
||||||
|
"return" 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
|
||||||
|
... return
|
||||||
|
... 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 ?
|
||||||
|
StopIteration
|
||||||
|
|
||||||
|
However, 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 4
|
||||||
|
|
||||||
|
Generators can call other generators:
|
||||||
|
|
||||||
|
>>> def zrange(n):
|
||||||
|
... for i in yrange(n):
|
||||||
|
... yield i
|
||||||
|
...
|
||||||
|
>>> list(zrange(5))
|
||||||
|
[0, 1, 2, 3, 4]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__test__ = {"simple": simple_tests}
|
||||||
|
|
||||||
|
# Magic test name that regrtest.py invokes *after* importing this module.
|
||||||
|
# This worms around a bootstrap problem.
|
||||||
|
# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
|
||||||
|
# so this works as expected in both ways of running regrtest.
|
||||||
|
def test_main():
|
||||||
|
import doctest, test_generators
|
||||||
|
doctest.testmod(test_generators)
|
||||||
|
|
||||||
|
# This part isn't needed for regrtest, but for running the test directly.
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue