iter (noun, genitive itineris); n, third declension
Обект с метод __next__(), който:
StopIterationОбикновено не викате obj.__next__(), а ползвате вградената next(obj), която го прави вместо вас
Вградената функция, която приема един аргумент и връща итератор за него. Работи както очаквате за вградети типове - list, tuple.
>>> i = iter([1, 2])
>>> next(i)
1
>>> next(i)
2
>>> next(i)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
for target in sequence:
блок
iter(sequence) за да вземе итераторnext() върху него. Прекратява ако той предизвика StopIteration.target към върната стойност и изпълнява блокАко искаме наш обект да може да бъде итериран чрез for имаме избор:
__getitem____iter__Ако изберете този подход, __iter__ трябва да връща обект, който има метод __next__(). Вече знаете как той трябва да работи
class Primes:
def __init__(self, limit):
self.limit = limit
self.last = 1
def __next__(self):
while self.limit > self.last:
self.last += 1
if all([self.last % n for n in range(2, self.last)]):
return self.last
raise StopIteration
def __iter__(self): return self
print(list(Primes(13)))
Ако не сте дефинирали __iter__, тогава функцията iter() ще провери дали вашия обект няма __getitems__. Ако да, тя сама конструира итератор, работещ така:
IndexError.
class Vector(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __getitem__(self, index):
if index == 0: return self.x
elif index == 1: return self.y
elif index == 2: return self.z
else: raise IndexError
squares = (n ** 2 for n in range(100000000))
for square in squares:
print(square)
if square > 1000: break
Структурата на итераторите ни позволява…
Но:
Има, разбира се!
def no_comment(limit):
for number in range(2, limit + 1):
if all(number % i for i in range(2, number)):
yield number
to13 = no_comment(13)
print(next(to13))
print(next(to13))
print(next(to13))
yield се наричат генератори. Те са по-особени.__next__().__next__(), генератора се изпълнява като нормална функция.yield, изпълнението на функцията замръзва и __next__() връща стойността предадена на yield.__next__() върху обекта-генератор функцията продължава от същото място по същия начин.__next__() вдига StopIteration
def flat(collection):
for element in collection:
if isinstance(element, (list, tuple)):
for x in flat(element): yield x
else:
yield element
print(list(flat([1, 2, [3, 4, 5], 5, [6, [7, [8, 9], 10], 11]])))
def fib():
x, y = 0, 1
while(True):
yield y
x, y = y, x + y