迭代器 Iterator

迭代器是一种对象,该对象包含值的可计数数字。

迭代器是可迭代的对象,这意味着您可以遍历所有值。

从技术上讲,在 Python 中,迭代器是实现迭代器协议的对象,它包含方法 iter() 和 next()。

str = 'abcd'
print(str)
it = iter(str)
print(it)
print(next(it))
print(next(it))


##   结果 
abcd
<str_ascii_iterator object at 0x00000000015AC4C0>
a
b


mytuple = ("apple", "banana", "cherry")
#  返回一个迭代器
myit = iter(mytuple)

print(next(myit))
print(next(myit))
print(next(myit))

在这里插入图片描述

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self

  def __next__(self):
    x = self.a
    self.a += 1
    return x

myclass = MyNumbers()
myiter = iter(myclass)

print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

在这里插入图片描述

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self

  def __next__(self):
    if self.a <= 20:
      x = self.a
      self.a += 1
      return x
    else:
      raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)

for x in myiter:
  print(x)

可迭代对象 Iterable

## for 循环实际上创建了一个迭代器对象,并为每个循环执行 next() 方法。
mystr = "banana"
for x in mystr:
  print(x)

在这里插入图片描述
在这里插入图片描述

from collections.abc import Iterable, Iterator

# 列表是可迭代对象,但不是迭代器
my_list = [1, 2, 3]
print(isinstance(my_list, Iterable))  # True
print(isinstance(my_list, Iterator))  # False

# 获取迭代器
my_iter = iter(my_list)
print(isinstance(my_iter, Iterator))  # True

# 使用迭代器
print(next(my_iter))  # 1
print(next(my_iter))  # 2
print(next(my_iter))  # 3
# print(next(my_iter))  # StopIteration

# 迭代器只能遍历一次
list2 = [1, 2, 3]
iter2 = iter(list2)
for i in iter2:
    print(i)  # 打印 1,2,3
# 再次遍历将没有任何输出
for i in iter2:
    print(i)  # 无输出
# 自定义可迭代对象
class MyIterable:
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        return MyIterator(self.data)

# 自定义迭代器
class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

# 使用
my_iterable = MyIterable([1, 2, 3])
for item in my_iterable:
    print(item)  # 1 2 3

在这里插入图片描述

可迭代对象不一定是迭代器

#  列表、集合、字符串、元组  是可迭代对象,但不是迭代器
# 列表 - 可迭代对象,但不是迭代器
my_list = [1, 2, 3, 4, 5]
print(type(my_list))  # <class 'list'>

# 可以 for 循环
for i in my_list:
    print(i)

# 但不能直接使用 next()
# next(my_list)  # TypeError: 'list' object is not an iterator

# 需要转换为迭代器才能使用 next()
list_iterator = iter(my_list)
print(next(list_iterator))  # 1

生成器

生成器是 Python 中一种特殊的迭代器,允许你逐个生成值,而不是一次性返回所有结果,从而节省内存。

》》生成器表达式 类似列表推导式,但使用圆括号:

num = [x for x in range(5) ] # 列表推导式,元组没有推导式
li = (x for x in range(5))   # 列表推导式的【】 改成(),就是生成器表达式
print(num)
print(li)
print(next(li))
print(next(li))
print(next(li)) 
## 结果
[0, 1, 2, 3, 4]
<generator object <genexpr> at 0x0000000001386080>
0
1
2


# 列表推导式(立即创建所有值)
list_squares = [x**2 for x in range(10)]  # 占用内存

# 生成器表达式(惰性求值)
gen_squares = (x**2 for x in range(10))    # 几乎不占内存

# 使用生成器
for square in gen_squares:
    print(square)
    
# 转换为列表(如果需要)
squares_list = list(gen_squares)

》》生成器函数 使用 yield 关键字定义:

生成器函数:函数体中如果出现了 yield 关键字,那该函数就是 生成器函数
生成器对象:调用 生成器函数 时,其函数体不会立刻执行,而是返回一个 生成器对象

写在 生成器函数中的代码,需要通过 生成器对象 来执行
1、调用 生成器对象的 生成器对象.next 方法 或 next(生成器对象) ,会让 生成器函数中的代码开始执行。
2、当生成器函数中的代码开始执行后,遇到 yield 会 “暂停”执行,并且其内部会记录“暂停”的位置。
3、后续调用 生成器对象.next() 或 next(生成器对象),都会从上一次“暂停”的位置,继续执行,直到再次遇到 yield。
4、遇到 return会抛出 stopIteration 异常,并将 return 后面的表达式,作为异常信息。
5、yield 后面所写的表达式,会作为本次 next() 或 next() 方法的返回值

# 基本生成器函数
def count_up_to(n):
    i = 1
    while i <= n:
        yield i
        i += 1

# 使用生成器   生成器是特殊的迭代器,迭代器一定是可迭代对象。反之就不一定
for num in count_up_to(5):
    print(num)  # 输出: 1 2 3 4 5

# 或者手动迭代
counter = count_up_to(3)
print(next(counter))  # 1
print(next(counter))  # 2
print(next(counter))  # 3
# print(next(counter))  # StopIteration 异常

在这里插入图片描述

yield from 能把一个  可迭代对象  里的东西依次 yield 出去 =>代替 for + yield

def demo():
    nums=range(1,6)
    for num in nums:
        yield num

for num in demo():
    print(num)
###############################
def demo2():
    nums = range(1, 6)
    yield from nums
    
for num in demo2():
    print(num)



# 生成器.send(值) 可以让生成器继续执行的同时,给上一次 yield 传值
# 备注1: next 只能取值,send 既能取值,也能送值
# 备注2:第一次启动生成器,不能传值
# 它允许你向生成器内部发送值,这个值会成为生成器中当前暂停的 yield 表达式的返回值。
def demo():
    print('AAAAAA')
    a = yield "===AAA====="
    print(a)
    print('BBBBBB')
    b= yield "=====BBBB====="
    print(b)
    print('cccccc')
    yield "=====CCCC====="

d = demo()
print(next(d))
print(d.send('zenzenzenzen'))
print(next(d))
=====结果====
AAAAAA
===AAA=====
zenzenzenzen
BBBBBB
=====BBBB=====
None
cccccc
=====CCCC=====

生成器表达式

无论是迭代器、还是生成器对象,都可以用list、tuple、set等直接拿到其里面的所有内容(注意:如果数据量很大,很占内存的,容易挤爆内存)
当 每个结果,只依赖当前这一个元素 。不依赖前后元素

nums = [10,20,30]
# 列表推导式  [表达式 for 变量 in 可迭代对象]
v01 = [n*2 for n in nums]
print(v01)
# 生成器推导式  (表达式 for 变量 in 可迭代对象)
v02 = (n * 2 for n in nums)
print(v02)   # v02 是生成器对象
print(list(v02))
v03 = (n * 2 for n in nums)
for n in v03:
    print(n)


结果
[20, 40, 60]
<generator object <genexpr> at 0x000000000142A9B0>
[20, 40, 60]
20
40
60

生成器 (Generator) vs 迭代器 (Iterator) VS 可迭代对象

迭代器是一个更广泛的概念,而生成器是创建迭代器的一种简便方式。

class MyIterator:
    """手动实现的迭代器"""
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration  # 手动抛出异常
        value = self.data[self.index]
        self.index += 1
        return value

# 使用迭代器
it = MyIterator([1, 2, 3])
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
# print(next(it))  # StopIteration


def my_generator(data):
    """生成器函数,自动处理迭代状态"""
    for item in data:
        yield item  # 自动暂停和恢复

# 使用生成器
gen = my_generator([1, 2, 3])
print(next(gen))  # 1
print(next(gen))  # 2
print(next(gen))  # 3
# print(next(gen))  # StopIteration 自动抛出


>>>迭代器:可能占用较多内存
class FileLineIterator:
    """文件行迭代器 - 一次加载所有行"""
    def __init__(self, filename):
        # 一次加载所有行到内存
        with open(filename, 'r') as f:
            self.lines = f.readlines()
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.lines):
            raise StopIteration
        line = self.lines[self.index]
        self.index += 1
        return line


>>>>>生成器:惰性求值,内存效率高
def file_line_generator(filename):
    """文件行生成器 - 逐行读取,内存友好"""
    with open(filename, 'r') as f:
        for line in f:
            yield line  # 一次只处理一行

# 处理大文件时内存效率极高
for line in file_line_generator('huge_file.txt'):
    process(line)  # 一次只处理一行
Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐