Итератори и генератори
„ Програмиране с Python“, ФМИ
17.03.2011
Въпроси (1)
a, b, c, d, e, *f, g, h, i, j, k = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
print(f[4])
Въпроси (2)
def sandwich(first_thing, *stuff):
return stuff.count('spam')
print(sandwich('spam', 'sausage', 'spam', 'spam',
'spam', 'sausage', 'spam', 'spam', 'spam'))
Въпроси (3)
def reversed(input):
result = input[::-1]
def keep_it_normal():
result = result[::-1]
keep_it_normal()
return result
print(reversed('abc'))
Въпроси (4)
l = lambda x, y: x**2 + y
print(l(2, 5))
Въпроси (5)
[x for x in range(1,10) if x % 3 == 0][2]
Преговор
- Какво можем да обходим с
for
?
for x in [1,2,3]: print(x)
for x in range(42): print(x)
for x in map(lambda x: 2*x, something): print(x)
Итератор
for
може да обхожда неща, за които можем да вземем итератор
- … а какво е итератор?
iter
и next
- Итератор е обект, съдържащ състоянието на обхождането
- Получаваме го извиквайки
iter
- Движим се по него извиквайки
next
Пример
iterator = iter([1,2,3])
while True:
x = next(iterator)
print(x)
iter
и next
(2)
- Получаваме
StopIteration
грешка, когато няма повече елементи
- Има начин да я обработим (
for
го прави вътрешно)
iter
и next
(3)
- Понякога итерираното съвпада с итератора
>>> m = map(lambda x: x*2, [1,2,3])
>>> iter(m) is m # True
True
- В тези случаи можем да викаме направо
next
m = map(lambda x: x*2, [1,2,3])
while True:
x = next(m)
print(x)
Въпрос
- Какво ще изведе следният код:
numbers = [1,2,3]
doubled = map(lambda x: x*2, l)
numbers[1] = 42
for x in doubled:
print(x)
yield
e:
- Албум на „Pearl Jam“
- Знак „дайте предимство“
- израз в Python
Пример за yield
def musicians():
yield 'Coltrane'
yield 'Davis'
yield 'Getz'
Прости числа с генератор
def primes():
number = 2
while True:
if all([number % divisor for divisor in range(2, number)]):
yield number
number += 1
Генератори
Генератори
def biscuits(pack):
pack.open()
while not pack.empty():
biscuit = pack.take_out()
yield biscuit
for biscuit in biscuits(favori):
if biscuit.examine():
biscuit.eat()
else:
biscuit.throw_away()
Generator expressions
primes = [n*n for n in range(2, 100)]
primes = (n*n for n in range(2, 100))
вградени функции
all()
, any()
map()
filter()
zip()
list()
, tuple()
, set()
- itertools
any
и all
- Какво ще се случи, когато изпълним следния код?
def endless():
yield True
while True:
yield False
any(endless())
enumerate
- Понякога ни се налага да имаме индекса и стойността
enumerate
(2)
- Понякога ни се налага да имаме индекса и стойността
- Едно [не-много-елегантно] решение:
names = ['Bird', 'Satchmo', 'Trane']
i = 0
for x in names:
print(i, x)
i += 1
enumerate
(3)
- Едно [по-елегантно] решение:
names = ['Bird', 'Satchmo', 'Trane']
for i, x in enumerate(names):
print(i, x)
zip
- Итерира няколко итеруеми едновременно
- дава n-торки при викане на
next
zip
(2)
tracks = ['Take the A Train', 'Mack the Knife', 'Alabama']
names = ['The Duke', 'Satchmo', 'Trane']
for track, name in zip(tracks, names):
print('{0} by {1}'.format(track, name))
Модулът itertools
- съдържа помощни функции за работа с итератори
Но първо…
- Какво е модул?
- Модулът е именовано пространство
- Съдържа обекти (функции, класове, модули, …)
Модули
import somemodule
somemodule.something
Модули (2)
from somemodule import something
from somemodule import *
itertools
dir(itertools)
help(itertools)