doctests = """ | |
########### Tests mostly copied from test_listcomps.py ############ | |
Test simple loop with conditional | |
>>> sum({i*i for i in range(100) if i&1 == 1}) | |
166650 | |
Test simple case | |
>>> {2*y + x + 1 for x in (0,) for y in (1,)} | |
set([3]) | |
Test simple nesting | |
>>> list(sorted({(i,j) for i in range(3) for j in range(4)})) | |
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] | |
Test nesting with the inner expression dependent on the outer | |
>>> list(sorted({(i,j) for i in range(4) for j in range(i)})) | |
[(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)] | |
Make sure the induction variable is not exposed | |
>>> i = 20 | |
>>> sum({i*i for i in range(100)}) | |
328350 | |
>>> i | |
20 | |
Verify that syntax error's are raised for setcomps used as lvalues | |
>>> {y for y in (1,2)} = 10 # doctest: +IGNORE_EXCEPTION_DETAIL | |
Traceback (most recent call last): | |
... | |
SyntaxError: ... | |
>>> {y for y in (1,2)} += 10 # doctest: +IGNORE_EXCEPTION_DETAIL | |
Traceback (most recent call last): | |
... | |
SyntaxError: ... | |
Make a nested set comprehension that acts like set(range()) | |
>>> def srange(n): | |
... return {i for i in range(n)} | |
>>> list(sorted(srange(10))) | |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
Same again, only as a lambda expression instead of a function definition | |
>>> lrange = lambda n: {i for i in range(n)} | |
>>> list(sorted(lrange(10))) | |
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
Generators can call other generators: | |
>>> def grange(n): | |
... for x in {i for i in range(n)}: | |
... yield x | |
>>> list(sorted(grange(5))) | |
[0, 1, 2, 3, 4] | |
Make sure that None is a valid return value | |
>>> {None for i in range(10)} | |
set([None]) | |
########### Tests for various scoping corner cases ############ | |
Return lambdas that use the iteration variable as a default argument | |
>>> items = {(lambda i=i: i) for i in range(5)} | |
>>> {x() for x in items} == set(range(5)) | |
True | |
Same again, only this time as a closure variable | |
>>> items = {(lambda: i) for i in range(5)} | |
>>> {x() for x in items} | |
set([4]) | |
Another way to test that the iteration variable is local to the list comp | |
>>> items = {(lambda: i) for i in range(5)} | |
>>> i = 20 | |
>>> {x() for x in items} | |
set([4]) | |
And confirm that a closure can jump over the list comp scope | |
>>> items = {(lambda: y) for i in range(5)} | |
>>> y = 2 | |
>>> {x() for x in items} | |
set([2]) | |
We also repeat each of the above scoping tests inside a function | |
>>> def test_func(): | |
... items = {(lambda i=i: i) for i in range(5)} | |
... return {x() for x in items} | |
>>> test_func() == set(range(5)) | |
True | |
>>> def test_func(): | |
... items = {(lambda: i) for i in range(5)} | |
... return {x() for x in items} | |
>>> test_func() | |
set([4]) | |
>>> def test_func(): | |
... items = {(lambda: i) for i in range(5)} | |
... i = 20 | |
... return {x() for x in items} | |
>>> test_func() | |
set([4]) | |
>>> def test_func(): | |
... items = {(lambda: y) for i in range(5)} | |
... y = 2 | |
... return {x() for x in items} | |
>>> test_func() | |
set([2]) | |
""" | |
__test__ = {'doctests' : doctests} | |
def test_main(verbose=None): | |
import sys | |
from test import test_support | |
from test import test_setcomps | |
test_support.run_doctest(test_setcomps, verbose) | |
# verify reference counting | |
if verbose and hasattr(sys, "gettotalrefcount"): | |
import gc | |
counts = [None] * 5 | |
for i in range(len(counts)): | |
test_support.run_doctest(test_setcomps, verbose) | |
gc.collect() | |
counts[i] = sys.gettotalrefcount() | |
print(counts) | |
if __name__ == "__main__": | |
test_main(verbose=True) |