0001 doctests = """ 0002 0003 Test simple loop with conditional 0004 0005 >>> sum(i*i for i in range(100) if i&1 == 1) 0006 166650 0007 0008 Test simple nesting 0009 0010 >>> list((i,j) for i in range(3) for j in range(4) ) 0011 [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] 0012 0013 Test nesting with the inner expression dependent on the outer 0014 0015 >>> list((i,j) for i in range(4) for j in range(i) ) 0016 [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)] 0017 0018 Make sure the induction variable is not exposed 0019 0020 >>> i = 20 0021 >>> sum(i*i for i in range(100)) 0022 328350 0023 >>> i 0024 20 0025 0026 Test first class 0027 0028 >>> g = (i*i for i in range(4)) 0029 >>> type(g) 0030 <type 'generator'> 0031 >>> list(g) 0032 [0, 1, 4, 9] 0033 0034 Test direct calls to next() 0035 0036 >>> g = (i*i for i in range(3)) 0037 >>> g.next() 0038 0 0039 >>> g.next() 0040 1 0041 >>> g.next() 0042 4 0043 >>> g.next() 0044 Traceback (most recent call last): 0045 File "<pyshell#21>", line 1, in -toplevel- 0046 g.next() 0047 StopIteration 0048 0049 Does it stay stopped? 0050 0051 >>> g.next() 0052 Traceback (most recent call last): 0053 File "<pyshell#21>", line 1, in -toplevel- 0054 g.next() 0055 StopIteration 0056 >>> list(g) 0057 [] 0058 0059 Test running gen when defining function is out of scope 0060 0061 >>> def f(n): 0062 ... return (i*i for i in xrange(n)) 0063 >>> list(f(10)) 0064 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 0065 0066 >>> def f(n): 0067 ... return ((i,j) for i in xrange(3) for j in xrange(n)) 0068 >>> list(f(4)) 0069 [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] 0070 >>> def f(n): 0071 ... return ((i,j) for i in xrange(3) for j in xrange(4) if j in xrange(n)) 0072 >>> list(f(4)) 0073 [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] 0074 >>> list(f(2)) 0075 [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)] 0076 0077 Verify that parenthesis are required in a statement 0078 0079 >>> def f(n): 0080 ... return i*i for i in xrange(n) 0081 Traceback (most recent call last): 0082 ... 0083 SyntaxError: invalid syntax 0084 0085 Verify early binding for the outermost for-expression 0086 0087 >>> x=10 0088 >>> g = (i*i for i in range(x)) 0089 >>> x = 5 0090 >>> list(g) 0091 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 0092 0093 Verify that the outermost for-expression makes an immediate check 0094 for iterability 0095 0096 >>> (i for i in 6) 0097 Traceback (most recent call last): 0098 File "<pyshell#4>", line 1, in -toplevel- 0099 (i for i in 6) 0100 TypeError: iteration over non-sequence 0101 0102 Verify late binding for the outermost if-expression 0103 0104 >>> include = (2,4,6,8) 0105 >>> g = (i*i for i in range(10) if i in include) 0106 >>> include = (1,3,5,7,9) 0107 >>> list(g) 0108 [1, 9, 25, 49, 81] 0109 0110 Verify late binding for the innermost for-expression 0111 0112 >>> g = ((i,j) for i in range(3) for j in range(x)) 0113 >>> x = 4 0114 >>> list(g) 0115 [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] 0116 0117 Verify re-use of tuples (a side benefit of using genexps over listcomps) 0118 0119 >>> tupleids = map(id, ((i,i) for i in xrange(10))) 0120 >>> max(tupleids) - min(tupleids) 0121 0 0122 0123 Verify that syntax error's are raised for genexps used as lvalues 0124 0125 >>> (y for y in (1,2)) = 10 0126 Traceback (most recent call last): 0127 ... 0128 SyntaxError: assign to generator expression not possible 0129 0130 >>> (y for y in (1,2)) += 10 0131 Traceback (most recent call last): 0132 ... 0133 SyntaxError: augmented assign to tuple literal or generator expression not possible 0134 0135 0136 0137 ########### Tests borrowed from or inspired by test_generators.py ############ 0138 0139 Make a generator that acts like range() 0140 0141 >>> yrange = lambda n: (i for i in xrange(n)) 0142 >>> list(yrange(10)) 0143 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 0144 0145 Generators always return to the most recent caller: 0146 0147 >>> def creator(): 0148 ... r = yrange(5) 0149 ... print "creator", r.next() 0150 ... return r 0151 >>> def caller(): 0152 ... r = creator() 0153 ... for i in r: 0154 ... print "caller", i 0155 >>> caller() 0156 creator 0 0157 caller 1 0158 caller 2 0159 caller 3 0160 caller 4 0161 0162 Generators can call other generators: 0163 0164 >>> def zrange(n): 0165 ... for i in yrange(n): 0166 ... yield i 0167 >>> list(zrange(5)) 0168 [0, 1, 2, 3, 4] 0169 0170 0171 Verify that a gen exp cannot be resumed while it is actively running: 0172 0173 >>> g = (me.next() for i in xrange(10)) 0174 >>> me = g 0175 >>> me.next() 0176 Traceback (most recent call last): 0177 File "<pyshell#30>", line 1, in -toplevel- 0178 me.next() 0179 File "<pyshell#28>", line 1, in <generator expression> 0180 g = (me.next() for i in xrange(10)) 0181 ValueError: generator already executing 0182 0183 Verify exception propagation 0184 0185 >>> g = (10 // i for i in (5, 0, 2)) 0186 >>> g.next() 0187 2 0188 >>> g.next() 0189 Traceback (most recent call last): 0190 File "<pyshell#37>", line 1, in -toplevel- 0191 g.next() 0192 File "<pyshell#35>", line 1, in <generator expression> 0193 g = (10 // i for i in (5, 0, 2)) 0194 ZeroDivisionError: integer division or modulo by zero 0195 >>> g.next() 0196 Traceback (most recent call last): 0197 File "<pyshell#38>", line 1, in -toplevel- 0198 g.next() 0199 StopIteration 0200 0201 Make sure that None is a valid return value 0202 0203 >>> list(None for i in xrange(10)) 0204 [None, None, None, None, None, None, None, None, None, None] 0205 0206 Check that generator attributes are present 0207 0208 >>> g = (i*i for i in range(3)) 0209 >>> expected = set(['gi_frame', 'gi_running', 'next']) 0210 >>> set(attr for attr in dir(g) if not attr.startswith('__')) >= expected 0211 True 0212 0213 >>> print g.next.__doc__ 0214 x.next() -> the next value, or raise StopIteration 0215 >>> import types 0216 >>> isinstance(g, types.GeneratorType) 0217 True 0218 0219 Check the __iter__ slot is defined to return self 0220 0221 >>> iter(g) is g 0222 True 0223 0224 Verify that the running flag is set properly 0225 0226 >>> g = (me.gi_running for i in (0,1)) 0227 >>> me = g 0228 >>> me.gi_running 0229 0 0230 >>> me.next() 0231 1 0232 >>> me.gi_running 0233 0 0234 0235 Verify that genexps are weakly referencable 0236 0237 >>> import weakref 0238 >>> g = (i*i for i in range(4)) 0239 >>> wr = weakref.ref(g) 0240 >>> wr() is g 0241 True 0242 >>> p = weakref.proxy(g) 0243 >>> list(p) 0244 [0, 1, 4, 9] 0245 0246 0247 """ 0248 0249 0250 __test__ = {'doctests' : doctests} 0251 0252 def test_main(verbose=None): 0253 import sys 0254 from test import test_support 0255 from test import test_genexps 0256 test_support.run_doctest(test_genexps, verbose) 0257 0258 # verify reference counting 0259 if verbose and hasattr(sys, "gettotalrefcount"): 0260 import gc 0261 counts = [None] * 5 0262 for i in xrange(len(counts)): 0263 test_support.run_doctest(test_genexps, verbose) 0264 gc.collect() 0265 counts[i] = sys.gettotalrefcount() 0266 print counts 0267 0268 if __name__ == "__main__": 0269 test_main(verbose=True) 0270
Generated by PyXR 0.9.4