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