Most can use for
Keyword traversal container All are iterator
for element in [1, 2, 3]: print(element) for element in (1, 2, 3): print(element) for key in {'one':1, 'two':2}: print(key) for char in "123": print(char) for line in open("myfile.txt"): print(line, end='')
This access is clear 、 concise 、 convenient .
The principle behind it is ,for
Statement on a container object iter()
. This function returns an iterator object , This object defines __next__()
Method , This method accesses the elements in one container at a time . When there are no more elements ,__next__()
Will trigger a StopIteration
abnormal , It tells for
Cycle termination .
You can use built-in functions next()
call __next__()
Method
>>> s = 'abc' >>> it = iter(s) >>> it <iterator object at 0x00A1DB50> >>> next(it) 'a' >>> next(it) 'b' >>> next(it) 'c' >>> next(it) Traceback (most recent call last): File "<stdin>", line 1, in <module> next(it) StopIteration
Add to class iterator act , You can do this by defining __iter__()
Method realization , This method returns a containing __next__()
The object of ; If the class is already defined __next__()
, __iter__()
Can return self
class Reverse: """Iterator for looping over a sequence backwards.""" def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def __next__(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index]
>>> rev = Reverse('spam') >>> iter(rev) <__main__.Reverse object at 0x00A1DB50> >>> for char in rev: ... print(char) ... m a p s
Python Of Iterator
Object represents a Data flow ,Iterator Objects can be next() Function call and continue to return the next data , Thrown until no data StopIteration
error . You can think of this data flow as an ordered sequence , But we can't know the length of the sequence in advance , It can only be passed continuously next() Function to calculate the next data on demand , therefore Iterator The calculation of is inert , It only calculates if it needs to return the next data .
Iterator
It can even represent an infinite data flow , For example, all natural numbers . While using list It's never possible to store all natural numbers .
According to this feature , We know iterator It can represent some infinite sequences , for example Fibonacci( Fibonacci ) The sequence , All prime numbers .
Be careful :list
、dict
、str
Equal data type is not Iterator
, But it can go through iter(obj)
Convert to an object
>>> from collections.abc import Iterable >>> isinstance([], Iterable) True
>>> from collections.abc import Iterator >>> isinstance((x for x in range(10)), Iterator) True
You build a custom container object , It contains a list 、 Tuples or other iteratable objects . You want to iterate directly on your new container object .
class Node: def __init__(self, value): self._value = value self._children = [] def __repr__(self): return 'Node({!r})'.format(self._value) def add_child(self, node): self._children.append(node) def __iter__(self): return iter(self._children) # Example if __name__ == '__main__': root = Node(0) child1 = Node(1) child2 = Node(2) root.add_child(child1) root.add_child(child2) # Outputs Node(1), Node(2) for ch in root: print(ch)
The depth first traversal is realized through iteration
class Node: def __init__(self, value): self._value = value self._children = [] def __repr__(self): return 'Node({!r})'.format(self._value) def add_child(self, node): self._children.append(node) def __iter__(self): return iter(self._children) def depth_first(self): yield self for c in self: yield from c.depth_first() # Example if __name__ == '__main__': root = Node(0) child1 = Node(1) child2 = Node(2) root.add_child(child1) root.add_child(child2) child1.add_child(Node(3)) child1.add_child(Node(4)) child2.add_child(Node(5)) for ch in root.depth_first(): print(ch) # Outputs Node(0), Node(1), Node(3), Node(4), Node(2), Node(5)
In this code ,depth_first()
The method is simple and intuitive . It first returns itself and iterates over each child node By calling the... Of the child node depth_first()
Method ( Use yield from
sentence ) Return the corresponding element .