详解python的迭代器、生成器以及相关的itertools包

iterators

>>> a = [1, 2]
>>> type(a)

>>> type(iter(a))

>>> it = iter(a)
>>> next(it)
1
>>> next(it)
2
>>> next(it)
traceback (most recent call last):
file “”, line 1, in
stopiteration
>>> len(a)
2
>>> len(it)
traceback (most recent call last):
file “”, line 1, in
typeerror: object of type ‘listiterator’ has no len()

class count_iterator(object):
n = 0
def __iter__(self):
return self
def next(self):
y = self.n
self.n += 1
return y

>>> counter = count_iterator()
>>> next(counter)
0
>>> next(counter)
1
>>> next(counter)
2
>>> next(counter)
3
>>> list(counter) # this will result in an infinite loop!

class simplelist(object):
def __init__(self, *items):
self.items = items
def __getitem__(self, i):
return self.items[i]

>>> a = simplelist(1, 2, 3)
>>> it = iter(a)
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
traceback (most recent call last):
file “”, line 1, in
stopiteration

q(n)=q(n-q(n-1))+q(n?q(n?2))

class qsequence(object):
def __init__(self, s):
self.s = s[:]
def next(self):
try:
q = self.s[-self.s[-1]] + self.s[-self.s[-2]]
self.s.append(q)
return q
except indexerror:
raise stopiteration()
def __iter__(self):
return self
def current_state(self):
return self.s

>>> q = qsequence([1, 1])
>>> next(q)
2
>>> next(q)
3
>>> [next(q) for __ in xrange(10)]
[3, 4, 5, 5, 6, 6, 6, 8, 8, 8]

generators

def count_generator():
n = 0
while true:
yield n
n += 1

>>> counter = count_generator()
>>> counter

>>> next(counter)
0
>>> next(counter)
1
>>> iter(counter)

>>> iter(counter) is counter
true
>>> type(counter)

a = s[:]
while true:
try:
q = a[-a[-1]] + a[-a[-2]]
a.append(q)
yield q
except indexerror:
return

… x = x0
… while true:
… yield x
… x = mu * min(x, 1.0 – x)

>>>
>>> t = tent_map(2.0, 0.1)
>>> for __ in xrange(30):
… print t.next()

0.1
0.2
0.4
0.8
0.4
0.8
0.4
0.8
0.4
0.8
0.4
0.8
0.4
0.8
0.4
0.8
0.4
0.799999999999
0.400000000001
0.800000000003
0.399999999994
0.799999999988
0.400000000023
0.800000000047
0.399999999907
0.799999999814
0.400000000373
0.800000000745
0.39999999851
0.79999999702

def collatz(n):
yield n
while n != 1:
n = n / 2 if n % 2 == 0 else 3 * n + 1
yield n

>>> # if the collatz conjecture is true then list(collatz(n)) for any n will
… # always terminate (though your machine might run out of memory first!)
>>> list(collatz(7))
[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
>>> list(collatz(13))
[13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
>>> list(collatz(17))
[17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
>>> list(collatz(19))
[19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]

recursive generators

def permutations(items):
if len(items) == 0:
yield []
else:
pi = items[:]
for i in xrange(len(pi)):
pi[0], pi[i] = pi[i], pi[0]
for p in permutations(pi[1:]):
yield [pi[0]] + p

>>> for p in permutations([1, 2, 3]):
… print p

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

generator expressions

>>> g = (x ** 2 for x in itertools.count(1))
>>> g

>>> next(g)
1
>>> next(g)
4
>>> iter(g)

>>> iter(g) is g
true
>>> [g.next() for __ in xrange(10)]
[9, 16, 25, 36, 49, 64, 81, 100, 121, 144]

>>> g = (random.random() < 0.4 for __ in itertools.count()) >>> [g.next() for __ in xrange(10)]
[false, false, false, true, true, false, true, false, false, true]

>>> sum(x ** 2 for x in xrange(10))
285

itertools模块

itertools模块提供了一系列迭代器能够帮助用户轻松地使用排列、组合、笛卡尔积或其他组合结构。

[0, 0, 1, 9, 72, 600, 5400, 52920, 564480, 6531840]
>>> [math.factorial(n) * n * (n – 1) / 4 for n in xrange(10)]
[0, 0, 1, 9, 72, 600, 5400, 52920, 564480, 6531840]

def count_fixed_points(p):
“””return the number of fixed points of p as a permutation.”””
return sum(1 for x in p if p[x] == x)
def count_partial_derangements(n, k):
“””returns the number of permutations of n with k fixed points.”””
return sum(1 for p in itertools.permutations(xrange(n)) if count_fixed_points(p) == k)

# usage:
>>> [count_partial_derangements(6, i) for i in xrange(7)]
[265, 264, 135, 40, 15, 0, 1]

Posted in 未分类