python3_迭代器与生成器__ / __iter__() / __next__() / yield / next() / iter()

版权声明:本文为博主原创文章,未经博主允许不得转载,希望能在相互交流中共同成长。【大红色:一级标题 绿色:二级标题 二红色:三级标题 黄色:四级标题】 https://blog.csdn.net/admin_maxin/article/details/82052065

1. 可用于for循环的数据类型有一下几种:

        (1)集合数据类型:list, tuple, dict, set, str, bytes

        (2)generator(数据结构):生成器、带yield的generator function

2. 可迭代对象(iterable):可直接作为for循环的对象,统称为可迭代对象。python从可迭代对象中获取迭代器。但凡是可以返回一个迭代器的对象都可称之为可迭代对象。

3. 生成器都是迭代器,迭代器不一定是生成器

1.迭代器

1. 迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器

2. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退

3. 迭代器有两个基本的方法:iter() 和 next()

4. 可使用isinstance()判断一个对象是否是迭代器对象(Iterator)

5. Python3中range(n)生成的是迭代器对象; python2中xrange(n)生成的才是迭代器对象

(a)iter()通过数据结构创建迭代器

1. 字符串,列表,元组,集合对象都可用于创建迭代器

import sys

str = "hello str"
lt = [1, 2, 3]
tp = (11, 22, 33)
st = set([111, 222, 333])

str_iter = iter(str)
print(next(str_iter))
print(next(str_iter))
print("*" * 100)

lt_iter = iter(lt)
print(next(lt_iter))
print(next(lt_iter))
print("*" * 100)

tp_iter = iter(tp)
print(next(tp_iter))
print(next(tp_iter))
print("*" * 100)

set_iter = iter(st)
set_iter = iter(st)
while True:
    try:
        print(next(set_iter))
    # StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
    except StopIteration as st:
        sys.exit(st.value)

(b)将类(class)改造成迭代器

1. 把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

2. __iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。

3. __next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。

# 类迭代器
# 必须在类内部实现 __iter__() / __next__()两个方法
class Eg2(object):
    """
    可迭代对象:从python内部获取迭代器
    """
    def __init__(self, text):
        # type:list
        self.sub_text = text.split(" ")

    def __iter__(self):
        return Eg2Iterator(self.sub_text)


class Eg2Iterator:
    """
    迭代器:对已经划分完毕的字符串进行迭代
    """
    def __init__(self, sub_text):
        self.sub_text = sub_text
        self.index = 0

    def __next__(self):
        try:
            subtext = self.sub_text[self.index]
        except IndexError:
            raise StopIteration()
        self.index += 1
        return subtext

    def __iter__(self):
        return self


if "__main__" == __name__:

    o2 = Eg2("hello, the wonderful new world!")
    for i in o2:
        print(i, end=" | ")

(c)方法或函数改造成迭代器(生成器为特殊的迭代器)

此处不做详细说明。具体改造如下:

class Eg2(object):

    def __init__(self, text):
        # type:list
        self.sub_text = text.split(" ")

    def __iter__(self):
        # 以下三种方式均可
        for item in self.sub_text:
            yield item
        # yield from self.sub_text
        # return (item for item in self.sub_text)


if "__main__" == __name__:

    o2 = Eg2("hello, the wonderful new world!")
    for i in o2:
        print(i, end=" | ")

2.生成器

1. inspect模块中isgeneratorfunction()能够判断一个函数是否为生成器函数

(a)生成器的定义与使用

1. 在Python中使用了yield的函数称为生成器

2. 什么时候使用yield: 一个函数 f,f 返回一个 list,这个 list 是动态计算出来的(不管是数学上的计算还是逻辑上的读取格式化),并且这个 list 会很大(无论是固定很大还是随着输入参数的增大而增大),这个时候,我们希望每次调用这个函数并使用迭代器进行循环的时候一个一个的得到每个 list 元素而不是直接得到一个完整的 list 来节省内存,这个时候 yield 就很有用。

3. 生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。仅需要一个yield关键字。

4. 任何生成器也是以一种懒加载的模式生成值

5. 生成器相比其它容器对象它更能节省内存和CPU。执行一次运算一次。

6. 生成器中的元素第一之后并不实际生成

7. 在一个 generator function 中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

# 4.生成器
def fibonacci(n):
    a = 0
    b = 1
    count = 0
    while count < n:
        yield b
        a, b = b, a+b
        count += 1
    
    # StopIteration.value
    return "--这是异常时打印的信息--"


if "__main__" == __name__:
    
    # a = fibonacci(10)
    # for i in range(10):
    #     print(a.__next__())

    g = fibonacci(5)
    while True:
        try:
            # def next(iterator, default=None)
            # 当迭代器遍历完毕后,x默认打印值为default
            x = next(g)
            print("g: ", x)
        except StopIteration as e:
            print("Generator return value: ", e.value)
            break

(b)生成器表达式

1. 生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。

# 生成器表达式
# 生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。
a = [i for i in range(10)]
b = (i for i in range(10))
print("sum(a): ", sum(a),", sum(b): ", sum(b))
print(type(a))  # <class 'list'>
print(type(b))  # <class 'generator'>

3.yield的使用解析

python3_生成器__yield 使用浅析

猜你喜欢

转载自blog.csdn.net/admin_maxin/article/details/82052065