Welcome, guest | Sign In | My Account | Store | Cart

An example which shows the power of decorators when combined with generators.

This recipe allows to generate different kinds of series of numbers by applying a decorator over an infinite integer generator. A processing function and a condition function can be used to specify the rules.

Python, 68 lines
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 # Simple series generator with # generators & decorators. # Author : Anand B Pillai # Beginning of recipe def myfunc(**kwds): def func(f): # Condition function cond = kwds['condition'] # Processing function proc = kwds['process'] # Number of items num = kwds['number'] x, l = 0, [] for item in f(): if cond and cond(item): if proc: item=proc(item) l.append(item) x += 1 if x==num: break return l return func def series(condition=None, process=None, number=10): """ Infinite integer generator """ @myfunc(condition=condition,process=process,number=number) def wrapper(): x = 1 while 1: yield x x += 1 return wrapper # End of recipe -----snip-------------snip------------------------- Examples. def prime(x): is_prime=True for y in range(2,int(pow(x,0.5)) + 1): if x % y==0: is_prime=False break return is_prime # Print first 10 prime numbers print series(condition=prime, process=None, number=10) [1, 2, 3, 5, 7, 11, 13, 17, 19, 23] # Print first 10 odd numbers print series(condition=lambda x: x%2, process=None, number=10) [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] # Print squares of first 10 numbers print series(condition=lambda x: x, process=lambda x: x*x, number=10) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] # Print a few random numbers import random print series(condition=lambda x: x, process=lambda x: random.random(), number=10)

This is a convenient way of extracting a required series with a required size out of a generator that returns an infinite stream of numbers.

Since we are using a generator instead of a list comprehension or FP tools such as map/filter, memory is saved for large series. Also custom processing can be done on the items of the series which allows you to write all kinds of series using this recipe.

The generator can also be modified to do some processing of its own, something which it does not do currently.

#### 1 comment

Raymond Hettinger 17 years, 4 months ago

Generator expressions offer better flexibility, speed, and economy of expression. Since the condition, process, and counter do not share a namespace, lambdas have to be used to specify the expression variable. This is slow, verbose, and clumsy compared to equivalent generator expressions.

If itertools.count is used to generate the series inputs, you get the additional advantage of being able to specify the starting count (from zero, from one, or anywhere else).

Also, itertools.islice() is a flexibile tool for extracting the first n elements of a series. However, more versatility can come from a design that allows an infinite series to be generated simply by dropping the enclosing islice().

>>> from itertools import count, islice
>>> def take(n, iterable):
return list(islice(iterable, n))

>>> take(10, (x for x in count(1) if prime(x)))
[1, 2, 3, 5, 7, 11, 13, 17, 19, 23]
>>> take(10, (x for x in count() if x%2))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
>>> take(10, (x*x for x in count(1)))
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> import random
>>> take(10, (random.random() for x in count()))
[0.94710345491708259, 0.4736249879152532, 0.059853883359122562, 0.65141323268525519, 0.60859729173749066, 0.82585367661224152, 0.91566522952506124, 0.43985135483694404, 0.43158061837573281, 0.16226950910826099]

# Combined example:  first ten squares of primes over 4
>>> take(10, (x*x for x in count(4) if prime(x)))
[25, 49, 121, 169, 289, 361, 529, 841, 961, 1369]

# Example of flexibility and simplicity of an infinite generator:
>>> zip(xrange(5), (x*x for x in count(2) if prime(x)))
[(0, 4), (1, 9), (2, 25), (3, 49), (4, 121)]
 Created by Anand on Wed, 23 Feb 2005 (PSF)

### Required Modules

• (none specified)