|
5 | 5 | ... yield 1 |
6 | 6 | ... yield 2 |
7 | 7 |
|
| 8 | + >>> for i in f(): |
| 9 | + ... print i |
| 10 | + 1 |
| 11 | + 2 |
8 | 12 | >>> g = f() |
9 | 13 | >>> g.next() |
10 | 14 | 1 |
|
203 | 207 | [1, 2, 4, 5, 8, 9, 10, 11] |
204 | 208 | >>> |
205 | 209 |
|
206 | | -
|
207 | 210 | Guido's binary tree example. |
208 | 211 |
|
209 | 212 | >>> # A binary tree class. |
|
301 | 304 | ... yield 3 |
302 | 305 | >>> list(g()) |
303 | 306 | [1, 2, 3] |
| 307 | +
|
| 308 | +A generator can't be resumed while it's already running. |
| 309 | +
|
| 310 | +>>> def g(): |
| 311 | +... i = me.next() |
| 312 | +... yield i |
| 313 | +>>> me = g() |
| 314 | +>>> me.next() |
| 315 | +Traceback (most recent call last): |
| 316 | + ... |
| 317 | + File "<string>", line 2, in g |
| 318 | +ValueError: generator already executing |
304 | 319 | """ |
305 | 320 |
|
306 | 321 | # Fun tests (for sufficiently warped notions of "fun"). |
|
338 | 353 | >>> primes = sieve(intsfrom(2)) |
339 | 354 | >>> firstn(primes, 20) |
340 | 355 | [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71] |
| 356 | +
|
| 357 | +Another famous problem: generate all integers of the form |
| 358 | + 2**i * 3**j * 5**k |
| 359 | +in increasing order, where i,j,k >= 0. Trickier than it may look at first! |
| 360 | +Try writing it without generators, and correctly, and without generating |
| 361 | +3 internal results for each result output. |
| 362 | +
|
| 363 | +>>> def times(n, g): |
| 364 | +... for i in g: |
| 365 | +... yield n * i |
| 366 | +>>> firstn(times(10, intsfrom(1)), 10) |
| 367 | +[10, 20, 30, 40, 50, 60, 70, 80, 90, 100] |
| 368 | +
|
| 369 | +>>> def merge(g, h): |
| 370 | +... ng = g.next() |
| 371 | +... nh = h.next() |
| 372 | +... while 1: |
| 373 | +... if ng < nh: |
| 374 | +... yield ng |
| 375 | +... ng = g.next() |
| 376 | +... elif ng > nh: |
| 377 | +... yield nh |
| 378 | +... nh = h.next() |
| 379 | +... else: |
| 380 | +... yield ng |
| 381 | +... ng = g.next() |
| 382 | +... nh = h.next() |
| 383 | +
|
| 384 | +This works, but is doing a whale of a lot or redundant work -- it's not |
| 385 | +clear how to get the internal uses of m235 to share a single generator. |
| 386 | +Note that me_times2 (etc) each need to see every element in the result |
| 387 | +sequence. So this is an example where lazy lists are more natural (you |
| 388 | +can look at the head of a lazy list any number of times). |
| 389 | +
|
| 390 | +>>> def m235(): |
| 391 | +... yield 1 |
| 392 | +... me_times2 = times(2, m235()) |
| 393 | +... me_times3 = times(3, m235()) |
| 394 | +... me_times5 = times(5, m235()) |
| 395 | +... for i in merge(merge(me_times2, |
| 396 | +... me_times3), |
| 397 | +... me_times5): |
| 398 | +... yield i |
| 399 | +
|
| 400 | +>>> result = m235() |
| 401 | +>>> for i in range(5): |
| 402 | +... print firstn(result, 15) |
| 403 | +[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24] |
| 404 | +[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80] |
| 405 | +[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192] |
| 406 | +[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384] |
| 407 | +[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675] |
341 | 408 | """ |
342 | 409 |
|
343 | 410 | __test__ = {"tut": tutorial_tests, |
|
0 commit comments