python迭代器和可迭代对象的学习总结(自学,仅供参考)

1.迭代器和可迭代对象详细介绍

1.1 了解python魔法方法

  • 是一种特殊的方法,其名称以双下划线开头和结尾,例如_init_()、_str_()、_iter_()等。这些特殊方法由Python解释器在特定情况下自动调用,而不是由用户代码显式调用。

1.1.1 魔法方法__iter__() 和__next__()

  • 先说结论:_iter_()和__next__()是Python中用于实现迭代器的两个重要魔法方法,它们分别用于定义可迭代对象和迭代器的行为。
  • python内置方法
    • iter(): iter(可迭代对象) -> 迭代器对象 # 将迭代对象转化为迭代器 ;实际上是在调用对象object的__iter__()方法,返回一个迭代器对象。
    • next(): Return the next item from the 返回迭代器的首个(下一个)元素 iterator.实际上是在调用对象object的__next__()方法,返回迭代器对象下一个元素。

1.2 什么是可迭代对象(Iterable)?

  • 可迭代对象(Iterable)是可以被迭代的对象,它实现了__iter__()方法,该方法返回一个迭代器对象(Iterator)。常见的可迭代对象包括列表、元组、集合等

  • 当我们使用iter()函数对可迭代对象进行迭代时,Python会隐式地调用该对象的__iter__()方法来获取对应的迭代器。

range(10) # 可迭代对象

print(iter(range(10))) #  iter(可迭代对象) -> 迭代器对象 
# 等价于
print(range(10).__iter__()) # 迭代器对象调用魔法方法__iter__() -> 迭代器对象
  • 迭代器是一种能够实现惰性计算的对象,它只会在需要时生成下一个值,从而节省内存空间。迭代器可以通过next()函数来逐个获取其元素
# 类型:列表;列表属于可迭代对象, 但不是迭代器
列表元素越多,占用的内存空间越大;
print(sys.getsizeof([i for i in range(100)]))  # 大小: 912 bytes
print(sys.getsizeof([i for i in range(10000000)]))  # 大小:81528056 bytes

print(sys.getsizeof(iter([i for i in range(100)]))) # 大小: 56 bytes
print(sys.getsizeof(iter([i for i in range(10000000)]))) # 大小: 56 bytes

# 类型:迭代器;不管num多大,占用内存空间不变;
# range(num)返回的是一个迭代器对象
print(sys.getsizeof(range(100)))  # 大小48 bytes
print(sys.getsizeof(range(10000000)))  # 大小:48 bytes

1.3 什么是迭代器(Iterator)?

  • 迭代器(Iterator)是一个对象,它实现了迭代器协议,也就是实现了__iter__()和__next__()方法的对象。
ite = iter(range(10)) #  iter(可迭代对象) -> 迭代器对象 
print(next(ite)) # 打印 0  等价于ite.__next__()
print(next(ite)) # 打印 1  等价于ite.__next__()
... # 每执行一次next(迭代器对象) -> 顺序输出元素
  • 总结一下:
    • 迭代器是实现了迭代器协议(即__iter__()和__next__()方法)的对象,可以逐个访问其元素;
    • 可迭代对象是可以被迭代的对象,包含__iter__()且该方法返回一个迭代器,从而来实现迭代。
    • 通常情况下,可迭代对象包含了迭代器

1.4 如何判断一个对象是可迭代对象,还是迭代器?

from typing import Iterable, Iterator

print(isinstance(iter([1, 2, 3, 4]), Iterable))  # True
print(isinstance(iter([1, 2, 3, 4]), Iterator))  # True
print(isinstance([1, 2, 3, 4], Iterable))  # True
print(isinstance([1, 2, 3, 4], Iterator))  # False 原因:[1, 2, 3, 4]列表是一个可迭代对象,不是迭代器对象,需要使用内置方法iter()获取该对象的迭代器对象

1.5 手搓对象实现range的部分功能,进一步理解可迭代对象和迭代器之间的关系


# 可迭代对象(内置魔法方法__iter__,可以返回一个生成器对象MyRangeIterator)
class MyRange: 
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        # 返回一个迭代器对象
        return MyRangeIterator(self.start, self.end)

# 迭代器对象(内置魔法方法__iter__和__next__,可以通过内置方法next(迭代器对象)逐个访问迭代器元素)
class MyRangeIterator: 
    def __init__(self, start, end):
        self.current = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        else:
            value = self.current
            self.current += 1
            return value


iterable = MyRange(1, 10)  # MyRange实例化获取到 -> 可迭代对象
iterator = iter(iterable)  # python解释器隐式调用实例对象iterable中的魔法方法__iter__()获取 -> 迭代器对象
print(next(iterator))  # 1  获取迭代器首个(下一个)元素

iterable = MyRangeIterator(1, 10)  # MyRangeIterator实例化获取到 -> 可迭代对象(因为该对象包含(实现)了__iter__()和__next__()方法,同时也是一个迭代器对象)
iterator = iter(iterable)  # python解释器隐式调用实例对象iterable中的魔法方法__iter__()获取 -> 迭代器对象
print(next(iterator))  # 1 获取迭代器首个(下一个)元素

1.6 迭代器的使用方式

在Python中,迭代器的使用方式可以归纳为以下几种:

  1. 使用for循环: 这是最常见的方式,使用for循环可以遍历迭代器中的每个元素。

    my_iterator = iter([i for i in range(1000)]) 
    for item in my_iterator:
        print(item)
    
  2. 调用next()函数: 使用next()函数可以逐个获取迭代器中的元素,当迭代结束时会抛出StopIteration异常。

    my_iterator = iter([i for i in range(1000)]) 
    while True:
        try:
            item = next(my_iterator)
            print(item)
        except StopIteration:
            break
    
  3. 使用list() tuple()``set()函数或者列表推导式和生成器推导式等:

     my_iterator = iter([i for i in range(1000)]) 
     my_list = list(my_iterator)
     my_tuple = tuple(my_iterator)
     my_set = set(my_iterator)
     my_list = [item for item in my_iterator]
     my_generator = (item for item in my_iterator)
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值