Home  >  Article  >  Backend Development  >  The difference between python generators and iterators

The difference between python generators and iterators

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼Original
2019-06-24 13:26:313498browse

For container objects such as list, string, tuple, dict, etc., it is very convenient to use a for loop to traverse. The iter() function is called on the container object in the background for statement. iter() is a python built-in function. The iter() function returns an iterator object that defines the next() method, which accesses the elements in the container one by one. next() is also a built-in function of Python. When there are no subsequent elements, next() will throw a StopIteration exception to notify the for statement of the end of the loop.

The difference between python generators and iterators

##Iterator

Iterator is used to help We record the position visited by each iteration. When we use the next() function on the iterator, the iterator will return to us the data at the next position of the recorded position. In fact, when using the next() function, the _next_ method of the iterator object is called (the _next_ method of the object in Python3, and the next() method of the object in Python2). Therefore, if we want to construct an iterator, we must implement its _next_ method. But this is not enough. Python requires that the iterator itself is also iterable, so we also need to implement the _iter_ method for the iterator, and the _iter_ method returns an iterator. The iterator itself is an iterator, so iteration The _iter_ method of the device can return itself.

Explanation of some terms:

1, Iterator protocol: The object needs to provide the next() method, which either returns the next item in the iteration, or causes A StopIteration exception to terminate the iteration.

2, iterable object: implements the iterator protocol object. List, tuple, and dict are all Iterable (iterable objects), but not Iterator (iterator objects). But you can use the built-in function iter() to turn these into Iterable (iterable objects).
3. The essence of the for item in Iterable loop is to first obtain the iterator of the iterable object Iterable through the iter() function, and then continuously call the next() method on the obtained iterator to obtain the next value and assign it. For item, the loop ends when a StopIteration exception is encountered.

Related recommendations: "

Python Video Tutorial"

Python's own container object case:

# 随便定义一个list
listArray=[1,2,3]
# 使用iter()函数
iterName=iter(listArray)
print(iterName)
# 结果如下:是一个列表list的迭代器
# <list_iterator object at 0x0000017B0D984278>
 
print(next(iterName))
print(next(iterName))
print(next(iterName))
print(next(iterName))#没有迭代到下一个元素,直接抛出异常
# 1
# 2
# 3
# Traceback (most recent call last):
# File "Test07.py", line 32, in <module>
# StopIteration

One of Python implements the _iter_ method and The class object of the _next_ method is an iterator. The following case is a case of calculating the Fibonacci sequence

class Fib(object):
 def __init__(self, max):
  super(Fib, self).__init__()
  self.max = max
 
 def __iter__(self):
  self.a = 0
  self.b = 1
  return self
 
 def __next__(self):
  fib = self.a
  if fib > self.max:
   raise StopIteration
  self.a, self.b = self.b, self.a + self.b
  return fib
 
# 定义一个main函数,循环遍历每一个菲波那切数
def main():
 # 20以内的数
 fib = Fib(20)
 for i in fib:
  print(i)
 
# 测试
if __name__ == &#39;__main__&#39;:
 main()

Explanation:

In the implementation of this class , a _iter_(self) method is defined. This method is called by iter() when the for loop traverses and returns an iterator. Because when traversing, the Python built-in function iter() is directly called, and iter() obtains the iterator of the object by calling _iter_(self). With an iterator, you can traverse elements one by one. When traversing one by one, the built-in next() function is also used to traverse the iterator object by calling the _next_(self) method of the object. So we need to implement the two methods _iter_(self) and _next_(self).


And because the _next_(self) method is implemented, when implementing _iter_(self), just return self directly.


The summary is:


When looping through the custom container object, the python built-in function iter() will be used to call the _iter_(self) of the traversed object to obtain An iterator, and then the loop uses next() on this iterator to call _next_(self) of the iterator object.


Note: _iter_(self) will only be called once, and _next_(self) will be called n times until a StopIteration exception occurs.

Generator

Function:

Delay operation. That is, results are produced when needed, not immediately.

Note:

The generator can only be traversed once.

Generator is a special type of iterator.

Classification:

第一类:生成器函数:还是使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

# 菲波那切数列
def Fib(max):
 n, a, b = 0, 0, 1
 while n < max:
  yield b
  a, b = b, a + b
  n = n + 1
 return &#39;亲!没有数据了...&#39;
# 调用方法,生成出10个数来
f=Fib(10)
# 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中
while True:
 try:
  x=next(f)
  print("f:",x)
 except StopIteration as e:
  print("生成器最后的返回值是:",e.value)
  break

第二类:生成器表达式:类似于列表推导,只不过是把一对大括号[]变换为一对小括号()。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。

如下案例加以说明:   

# 一个列表
xiaoke=[2,3,4,5]
# 生成器generator,类似于list,但是是把[]改为()
gen=(a for a in xiaoke)
for i in gen:
 print(i)
#结果是:
2
3
4
5
# 为什么要使用生成器?因为效率。
# 使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。
# 如果你构造一个列表(list)的目的仅仅是传递给别的函数,
# 比如 传递给tuple()或者set(), 那就用生成器表达式替代吧! 
#本案例是直接把列表转化为元组
kk=tuple(a for a in xiaoke)
print(kk)
#结果是:
(2, 3, 4, 5) 
# python内置的一些函数,可以识别这是生成器表达式,外面有一对小括号,就是生成器
result1=sum(a for a in range(3))
print(result1)
# 列表推导式
result2=sum([a for a in range(3)])
print(result2)

区别:

生成器能做到迭代器能做的所有事,而且因为自动创建了 iter()和 next()方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration 异常。

The above is the detailed content of The difference between python generators and iterators. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn