程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

What is the principle behind Pythons for loop?

編輯:Python
python iterators

One 、 What is? iterators( iterator )?

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

Two 、 How to construct and call iterators?

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

3、 ... and 、iterators Which scenes are commonly used ?

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 :listdictstr 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

Four 、iterators actual combat

Agent iteration

problem

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 .

Solution

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)

Implement the iterator protocol

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 .

Reference resources

  1. https://docs.python.org/3/tutorial/classes.html#iterators
  2. https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640
  3. https://python3-cookbook.readthedocs.io/zh_CN/latest/c04/p02_delegating_iteration.html

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved