迭代器和生成器

迭代器和生成器

1.迭代器

1.1 迭代器类型的定义;

  • 当类中定义了__iter____nxet__两个方法。

  • __iter__方法需要返回本身即self

  • __nxet__方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。

  • # 创建迭代器类型
    class IT(object):
        def __init__(self):
            self.counter=0
    
        def __iter__(self):
            return self#返回self
        def __next__(self):
            self.counter+=1
            if self.counter==3:
                raise StopIteration#没有数据时抛出异常
            return self.counter#返回下一个数据。
    

1.2 迭代器对象

  • 根据实例化创建一个迭代对象

  • # 根据实例化创建迭代器对象
    
    obj1=IT()
    
    v1=next(obj1)#next内置函数直接调用,obj1.__next__()
    print(v1)
    
    v2=obj1.__next__()
    print(v2)
    v3=next(obj1)
    print(v3)# 抛出异常,因为没有值了;
    
  • image-20211127145602993

  • 使用for循环迭代器对象

    for 循环内部在循环时,先执行__iter__方法,获取一个迭代对象,然后不断执行next()取值(有异常StopIteration则循环终止)

    # 迭代器对象支持通过next()取值,取值结束则会自动抛出StopIteration
    obj=IT()
    for item in obj:#首先会执行obj的__iter__方法,并获取返回值,一直去反复的执行next(对象)
        print(item)
    

1.3 补充dir()函数

  • dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。

  • 语法
    dir([object])
    # 参数可以是对象、变量、类型。
    
  • 返回值

    模块的属性列表。

  • image-20211127151243671

2.生成器

2.1 定义

  • 在函数体中使用了yield的函数成为生成器(generator);

  • 生成器是一种特殊迭代器

  • 在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在**下一次执行 next() **方法时从当前位置继续运行。

  • 调用一个生成器函数,返回的是一个生成器对象(迭代器对象)

  • 使用生成器可以节省内存

  • def func():
        print(111)
        yield 1
    
    obj1=func()
    print(obj1)#<generator object func at 0x0000000001E2E190>
    # 打印的是生成器对象;
    
  • 执行生成器函数,返回的是生成器对象

2.2 执行生成器

  • def func():
        print(111)
        yield 1
    
        print(222)
        yield 2
    
        print(333)
        yield 3
    obj1=func()
    print(obj1)#<generator object func at 0x0000000001E2E190>
    
    next(obj1)# 111
    next(obj1)# 222从yield之后的位置开始执行
    
    n1=next(obj1)# 333
    print(n1)# 3 获得yield返回的值
    next(obj1)# StopIteration超出范围
    

2.3 基于for循环执行生成器

  • data=func()
    for item in data:
        # next(data),相当于内部执行next(data)
        print(item)
    
  • image-20211127153805740

2.4 生成器的应用场景

  • image-20211127154037307

补充:生成器可以使用send()给生成其中赋值;

3.可迭代对象

3.1 定义

  • 如果一个类中有__iter__方法,返回的是迭代器对象;则我们成这个类创建的对象为可迭代对象。

  • 可迭代对象是可以用来for循环的,再循环内部其实是先执行__iter__方法,获取迭代器对象。然后再在内部执行迭代器对象的next功能逐步取值。

  • class Foo(object):
        def __iter__(self):
            return 迭代器对象
    obj=Foo()
    #obj就是可迭代对象
    
    for item in obj:
        pass
    
  • 通常迭代器会和可迭代对象一起使用

    # 定义迭代器对象
    class IT(object):
        def __init__(self):
            self.counter=0
    
        def __iter__(self):
            return self
        def __next__(self):
            self.counter+=1
            if self.counter==3:
                raise StopIteration
            return self.counter
    
    class Foo(object):
        def __iter__(self):
            return IT()
    
    obj=Foo()
    for item in obj:
        print(item)
    

    image-20211127155912447

  • 我们使用的range函数就是可迭代对象,因为他包含了__iter__方法

    image-20211127160630958

3.2 常见的可迭代对象

  • 能被for循环的数据类型都是可迭代对象;

    • 字符串
    • 列表
    • 元组
    • 字典
    • 集合
  • image-20211127161030328

3.3 判断是否是迭代器

from collections.abc import Iterator,Iterable
v1=[1,2,3]
print(isinstance(v1,Iterator)) #false  判断是否是迭代器  依据:__iter__ 和 __next__
v2=v1.__iter__()
print(isinstance(v2,Iterator))# True
# 判断可迭代
print(isinstance(v1,Iterable))# True   依据是否有__iter__且返回迭代器对象,一般和上面的判断结合使用
print(isinstance(v2,Iterable))# True

3.4 补充:isinstance函数

  • isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。

  • isinstance() 与 type() 区别:
    • type() 不会认为子类是一种父类类型,不考虑继承关系。
    • isinstance() 会认为子类是一种父类类型,考虑继承关系。
  • 如果要判断两个类型是否相同推荐使用 isinstance()。

  • 语法
    isinstance(object, classinfo)
    # object -- 实例对象。
    # classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。
    
  • 返回值

    如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。。

    image-20211127162423312

每天都是更接近成功的一天;

posted @ 2021-11-27 16:26  紫青宝剑  阅读(42)  评论(0编辑  收藏  举报