Python 中的迭代器可迭代对象生成器装饰器是四个重要但容易混淆的概念。它们各有不同的用途,理解它们的区别能让你写出更高效、更具 Python 风格的代码。

1. 可迭代对象(Iterable)

什么是可迭代对象?

一个可迭代对象是任何可以返回一个迭代器的对象。你可以把它想象成一个“容器”,里面装着可以逐个访问的元素。它内部实现了 __iter__() 方法,这个方法会返回一个迭代器。

怎么用?

  • 所有序列类型,比如列表(list)元组(tuple)和字符串(string),都是可迭代对象。

  • 字典(dict)、集合(set)和文件对象也是可迭代对象。

  • 你可以直接在 for 循环中使用可迭代对象。

示例:

my_list = [1, 2, 3]  # my_list 是一个可迭代对象

# for 循环会自动调用 my_list.__iter__() 来获取一个迭代器
for item in my_list:
    print(item)

2. 迭代器(Iterator)

什么是迭代器?

一个迭代器是一个“状态”对象,它知道如何遍历一个可迭代对象中的所有元素。它实现了两个关键方法:

  • __iter__():返回迭代器自身。

  • __next__():返回序列中的下一个元素。当没有更多元素时,它会抛出 StopIteration 异常。

怎么用?

通常你不需要手动创建迭代器,for 循环会为你处理这些。但如果你想手动控制迭代过程,可以使用 iter() 函数来获取一个可迭代对象的迭代器,然后使用 next() 函数来逐个获取元素。

示例:

my_list = [1, 2, 3]
my_iterator = iter(my_list)  # 获取迭代器

print(next(my_iterator))  # 输出: 1
print(next(my_iterator))  # 输出: 2
print(next(my_iterator))  # 输出: 3
# print(next(my_iterator)) # 再次调用会抛出 StopIteration 异常

区别总结:可迭代对象 vs. 迭代器

  • 可迭代对象是“容器”,它能被迭代。

  • 迭代器是“指针”,它记录迭代的当前位置。

  • for 循环的工作原理是:首先调用可迭代对象的 __iter__() 方法来获取一个迭代器,然后不断调用迭代器的 __next__() 方法,直到捕获到 StopIteration 异常。

3. 生成器(Generator)

什么是生成器?

生成器是一种特殊类型的迭代器,它可以“惰性”地生成值,而不是一次性将所有值存储在内存中。它通过 yield 关键字来生成值。当 yield 语句被执行时,函数会暂停执行并返回一个值,同时保留其内部状态。下一次调用 next() 时,函数会从暂停的地方继续执行。

怎么用?

有两种创建生成器的方式:

  • 生成器函数:包含 yield 关键字的函数。

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

示例:

# 生成器函数
def my_generator():
    yield 1
    yield 2
    yield 3

gen = my_generator() # gen 是一个生成器对象
print(next(gen)) # 输出: 1
print(next(gen)) # 输出: 2

# 生成器表达式
gen_exp = (x for x in [1, 2, 3])
print(next(gen_exp)) # 输出: 1

生成器 vs. 迭代器

  • 生成器是创建迭代器的一种简洁方式。

  • 生成器可以自动处理 StopIteration 异常和 __next__() 方法的实现,你只需使用 yield 关键字。

  • 生成器特别适合处理大量数据,因为它只在需要时才生成值,节省了大量内存。

4. 装饰器(Decorator)

什么是装饰器?

装饰器是一种特殊类型的函数,它接收另一个函数作为参数,并返回一个新的函数。它的主要作用是在不修改原始函数代码的情况下,给原始函数添加额外的功能(比如计时、日志记录、权限检查等)。

怎么用?

使用 @ 符号来应用装饰器,这是一种语法糖。

示例:

import time

def timer_decorator(func):
    """一个简单的计时装饰器"""
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)  # 调用原始函数
        end_time = time.time()
        print(f"函数 {func.__name__} 执行耗时: {end_time - start_time:.4f} 秒")
        return result
    return wrapper

@timer_decorator
def complex_task():
    """一个需要计时的复杂任务"""
    print("开始执行复杂任务...")
    time.sleep(2)
    print("复杂任务执行完毕!")

complex_task()

区别总结:装饰器 vs. 其他

  • 装饰器与迭代器、可迭代对象、生成器没有直接关系

  • 前三者(迭代器、可迭代对象、生成器)是关于数据访问和遍历的模式。

  • 装饰器是一种关于函数或类功能扩展的模式。它们解决的是完全不同的问题。

区别与总结

概念 作用 核心 典型用法
可迭代对象 容器,可被迭代 __iter__() 方法 for 循环
迭代器 状态,记录迭代位置 __next__() 方法 next() 函数
生成器 惰性生成值的迭代器 yield 关键字 内存优化,大数据处理
装饰器 扩展函数功能 @ 语法糖,高阶函数 日志、计时、权限控制

更多推荐