Python中iterable object,iterator和generator

iterable object

Python中的iterable object(可迭代对象)是指存储了元素的容器对象,并且该容器对象实现了__iter__()方法,容器对象中的元素可以通过__iter__()方法访问。

常见的iterable object有:

  • list、tuple、set、dict、str等序列类型或者集合
  • 文件对象
  • 在类定义中实现了__iter__()方法的对象
  • 迭代器和生成器(generator)

代码示例

class UserDefine(object):
    def __init__(self, data):
        self.data = data
        
    def __iter__(self):
        return iter(self.data)
    
    #def __getitem__(self, index):
    #    return self.data[index]
       
it_ob = [1, 2, 3, 4, 5]
user_define = UserDefine(it_ob)

import collections
print(isinstance(user_define,collections.Iterable))
print(isinstance(user_define,collections.Iterator))

for i in user_define:
    print(i)

上面代码中如果把__iter__()注释掉而改为实现已经注释了的__getitem__(),则同样可以使用for…in遍历user_define的元素,但是调用isinstance判断是否为Iterable时返回False。所以iterable object可以通过for…in循环遍历元素,但是可以通过for…in循环遍历元素的不一定是iterable object。


iterator

Python中的iterator(迭代器)是指存储了元素的容器对象,并且该容器对象同时实现了__iter__()和__next__()方法,每次调用该容器对象返回自身的下一个元素。其中__iter__()方法返回对象自身(对象自身必须为迭代器),而__next__()方法则显式得返回下一个元素。

当使用for…in循环遍历iterable object时实际包含2个操作:1、调用__iter__()返回一个迭代器,2、不断调用__next__()获取下一个元素直到返回StopIteration。

代码示例

class UserDefine(object):
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        self.index = 0
        return self

    def __next__(self):
        if self.index > len(self.data)-1:
            raise StopIteration
        out_data = self.data[self.index]
        self.index += 1
        return out_data
    
it_o = [1, 2, 3, 4, 5]
user_define = UserDefine(it_o)

import collections
print(isinstance(user_define,collections.Iterable))
print(isinstance(user_define,collections.Iterator))

for i in user_define:
    print(i)

generator

generator是Python的一种一边循环一边计算的机制。generator是一种特殊的迭代器,自动实现了"迭代器协议"(即__iter__()和__next__()方法),不需要再显式得实现这2个方法。创建方式主要有2种:

  • 列表生成式的[]改成()
  • 在函数中添加yield语句

代码示例

列表生成式的[]改成()

it_ob = [0,1,2,3,4]
gen = (i for i in it_ob)
import collections
print(isinstance(gen,collections.Iterable))
print(isinstance(geb,collections.Iterator))
for i in gen:
    print(i)

在函数中添加yield语句

def gen(num):
    i = 0
    while i < num:
        yield i
        i += 1
g = gen(5)

import collections
print(isinstance(g,collections.Iterable))
print(isinstance(g,collections.Iterator))
for i in g:
    print(i)

generator允许使用send()在迭代过程中对当前迭代值进行修改,如下:

def gen(num):
    i = 0
    while i < num:
        rec = yield i
        i = i + 1 if rec is None else rec
g = gen(5)

print(next(g))
print(next(g))
g.send(0)
print(next(g))
print(next(g))

你可能感兴趣的:(Python)