1doctests = """ 2########### Tests mostly copied from test_listcomps.py ############ 3 4Test simple loop with conditional 5 6 >>> sum({i*i for i in range(100) if i&1 == 1}) 7 166650 8 9Test simple case 10 11 >>> {2*y + x + 1 for x in (0,) for y in (1,)} 12 {3} 13 14Test simple nesting 15 16 >>> list(sorted({(i,j) for i in range(3) for j in range(4)})) 17 [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] 18 19Test nesting with the inner expression dependent on the outer 20 21 >>> list(sorted({(i,j) for i in range(4) for j in range(i)})) 22 [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)] 23 24Test the idiom for temporary variable assignment in comprehensions. 25 26 >>> sorted({j*j for i in range(4) for j in [i+1]}) 27 [1, 4, 9, 16] 28 >>> sorted({j*k for i in range(4) for j in [i+1] for k in [j+1]}) 29 [2, 6, 12, 20] 30 >>> sorted({j*k for i in range(4) for j, k in [(i+1, i+2)]}) 31 [2, 6, 12, 20] 32 33Not assignment 34 35 >>> sorted({i*i for i in [*range(4)]}) 36 [0, 1, 4, 9] 37 >>> sorted({i*i for i in (*range(4),)}) 38 [0, 1, 4, 9] 39 40Make sure the induction variable is not exposed 41 42 >>> i = 20 43 >>> sum({i*i for i in range(100)}) 44 328350 45 46 >>> i 47 20 48 49Verify that syntax error's are raised for setcomps used as lvalues 50 51 >>> {y for y in (1,2)} = 10 # doctest: +IGNORE_EXCEPTION_DETAIL 52 Traceback (most recent call last): 53 ... 54 SyntaxError: ... 55 56 >>> {y for y in (1,2)} += 10 # doctest: +IGNORE_EXCEPTION_DETAIL 57 Traceback (most recent call last): 58 ... 59 SyntaxError: ... 60 61 62Make a nested set comprehension that acts like set(range()) 63 64 >>> def srange(n): 65 ... return {i for i in range(n)} 66 >>> list(sorted(srange(10))) 67 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 68 69Same again, only as a lambda expression instead of a function definition 70 71 >>> lrange = lambda n: {i for i in range(n)} 72 >>> list(sorted(lrange(10))) 73 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 74 75Generators can call other generators: 76 77 >>> def grange(n): 78 ... for x in {i for i in range(n)}: 79 ... yield x 80 >>> list(sorted(grange(5))) 81 [0, 1, 2, 3, 4] 82 83 84Make sure that None is a valid return value 85 86 >>> {None for i in range(10)} 87 {None} 88 89########### Tests for various scoping corner cases ############ 90 91Return lambdas that use the iteration variable as a default argument 92 93 >>> items = {(lambda i=i: i) for i in range(5)} 94 >>> {x() for x in items} == set(range(5)) 95 True 96 97Same again, only this time as a closure variable 98 99 >>> items = {(lambda: i) for i in range(5)} 100 >>> {x() for x in items} 101 {4} 102 103Another way to test that the iteration variable is local to the list comp 104 105 >>> items = {(lambda: i) for i in range(5)} 106 >>> i = 20 107 >>> {x() for x in items} 108 {4} 109 110And confirm that a closure can jump over the list comp scope 111 112 >>> items = {(lambda: y) for i in range(5)} 113 >>> y = 2 114 >>> {x() for x in items} 115 {2} 116 117We also repeat each of the above scoping tests inside a function 118 119 >>> def test_func(): 120 ... items = {(lambda i=i: i) for i in range(5)} 121 ... return {x() for x in items} 122 >>> test_func() == set(range(5)) 123 True 124 125 >>> def test_func(): 126 ... items = {(lambda: i) for i in range(5)} 127 ... return {x() for x in items} 128 >>> test_func() 129 {4} 130 131 >>> def test_func(): 132 ... items = {(lambda: i) for i in range(5)} 133 ... i = 20 134 ... return {x() for x in items} 135 >>> test_func() 136 {4} 137 138 >>> def test_func(): 139 ... items = {(lambda: y) for i in range(5)} 140 ... y = 2 141 ... return {x() for x in items} 142 >>> test_func() 143 {2} 144 145""" 146 147 148__test__ = {'doctests' : doctests} 149 150def test_main(verbose=None): 151 import sys 152 from test import support 153 from test import test_setcomps 154 support.run_doctest(test_setcomps, verbose) 155 156 # verify reference counting 157 if verbose and hasattr(sys, "gettotalrefcount"): 158 import gc 159 counts = [None] * 5 160 for i in range(len(counts)): 161 support.run_doctest(test_setcomps, verbose) 162 gc.collect() 163 counts[i] = sys.gettotalrefcount() 164 print(counts) 165 166if __name__ == "__main__": 167 test_main(verbose=True) 168