news 2026/4/6 5:44:25

python 生成器、迭代器、动态新增属性及方法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python 生成器、迭代器、动态新增属性及方法

你想系统掌握 Python 中迭代器、生成器的核心概念与使用方法,同时学会给对象(类实例、自定义类)动态新增属性和方法,理解这些特性的底层逻辑和实际应用场景,写出更高效、灵活的 Python 代码。

下面分模块讲解,每个部分都配有可直接运行的示例,兼顾原理和实用性:


一、迭代器(Iterator):可逐个取值的「容器」

1.1 核心定义

迭代器是实现了「迭代器协议」的对象,必须满足两个条件:

  • 实现__iter__()方法:返回迭代器自身(用于兼容可迭代对象协议);
  • 实现__next__()方法:返回下一个元素,无元素时抛出StopIteration异常。

前置概念:可迭代对象(Iterable)

  • 像列表、字符串、字典这类能被for循环遍历的对象,都属于「可迭代对象」;
  • 可迭代对象实现了__iter__()方法,但未实现__next__()
  • 可通过iter()函数将「可迭代对象」转为「迭代器」。

1.2 基础用法示例

python

# 1. 可迭代对象转迭代器 nums = [1, 2, 3] # 列表是可迭代对象,不是迭代器 iter_nums = iter(nums) # 转为迭代器 # 2. 用next()取值(手动遍历) print(next(iter_nums)) # 输出:1 print(next(iter_nums)) # 输出:2 print(next(iter_nums)) # 输出:3 # print(next(iter_nums)) # 无元素,抛出 StopIteration 异常 # 3. for循环自动处理迭代器(自动调用next()和捕获异常) iter_nums2 = iter(nums) for num in iter_nums2: print(num) # 输出:1 2 3 # 4. 自定义迭代器(实现斐波那契数列) class FibIterator: def __init__(self, max_num): self.max_num = max_num # 最大项数 self.a, self.b = 0, 1 # 初始值 self.count = 0 # 已生成项数 # 实现__iter__,返回自身 def __iter__(self): return self # 实现__next__,生成下一个值 def __next__(self): if self.count < self.max_num: result = self.a self.a, self.b = self.b, self.a + self.b self.count += 1 return result else: raise StopIteration # 终止迭代 # 使用自定义迭代器 fib = FibIterator(5) for num in fib: print(num) # 输出:0 1 1 2 3

1.3 迭代器核心特点

  • 惰性计算:只在调用next()时生成下一个值,无需一次性加载所有数据,节省内存;
  • 单向遍历:只能从前往后取,无法回退或重置(除非重新创建迭代器);
  • 一次性:遍历完后无法再次使用(需重新生成)。

二、生成器(Generator):简化版迭代器

2.1 核心定义

生成器是特殊的迭代器,无需手动实现__iter__()__next__()(解释器自动实现),通过yield关键字创建,分为两种形式:

  1. 生成器函数:包含yield关键字的函数(而非return);
  2. 生成器表达式:类似列表推导式,用()代替[],更简洁。

2.2 生成器函数(核心用法)

  • 调用生成器函数时,不会立即执行函数体,而是返回一个「生成器对象」;
  • 执行到yield时,函数暂停并返回当前值,下次调用next()时从暂停处继续执行;
  • 函数执行完毕(无更多yield),自动抛出StopIteration

python

# 生成器函数实现斐波那契数列(对比自定义迭代器,代码大幅简化) def fib_generator(max_num): a, b = 0, 1 count = 0 while count < max_num: yield a # 暂停并返回当前值 a, b = b, a + b count += 1 # 使用生成器 fib = fib_generator(5) print(next(fib)) # 0 print(next(fib)) # 1 for num in fib: print(num) # 1 2 3 # 生成器支持直接遍历(无需手动转迭代器) fib2 = fib_generator(3) for num in fib2: print(num) # 0 1 1

2.3 生成器表达式(简洁写法)

python

# 生成器表达式(对比列表推导式) gen = (x * 2 for x in range(3)) # 生成器,惰性计算 lst = [x * 2 for x in range(3)] # 列表,一次性生成所有值 print(gen) # 输出:<generator object <genexpr> at 0x...> print(lst) # 输出:[0, 2, 4] # 遍历生成器 for num in gen: print(num) # 0 2 4 # 内存优势:处理大数据时,生成器远优于列表 # 比如生成1000万个数字,列表会占满内存,生成器几乎不占内存 big_gen = (x for x in range(10_000_000)) # big_lst = [x for x in range(10_000_000)] # 大概率触发内存不足

2.4 生成器核心特点

  • 比迭代器代码更简洁(无需写__iter__/__next__);
  • 完全继承迭代器的「惰性计算」「单向遍历」特性;
  • 支持send()方法(进阶):可在暂停时向生成器传入值,实现双向通信。

三、动态新增属性及方法(Python 动态语言特性)

Python 是动态语言,允许在运行时给「类」或「类实例」动态新增属性、方法(无需提前在类定义中声明)。

3.1 动态新增属性

(1)给实例新增属性(仅影响当前实例)

python

# 定义基础类 class Person: def __init__(self, name): self.name = name # 初始化属性 # 创建实例 p1 = Person("张三") print(p1.name) # 张三 # 动态新增实例属性 p1.age = 25 p1.gender = "男" print(p1.age) # 25 print(p1.gender) # 男 # 其他实例不受影响 p2 = Person("李四") # print(p2.age) # 报错:AttributeError: 'Person' object has no attribute 'age'
(2)给类新增属性(影响所有实例,包括已创建的)

python

# 给Person类新增类属性 Person.country = "中国" # 已创建的p1、p2都能访问该属性 print(p1.country) # 中国 print(p2.country) # 中国 # 新创建的实例也能访问 p3 = Person("王五") print(p3.country) # 中国

3.2 动态新增方法

需要借助types.MethodType将函数绑定为实例 / 类的方法,分为三种类型:

(1)动态新增实例方法(仅影响当前实例)

python

import types # 定义一个普通函数(待绑定为实例方法) def say_hello(self): print(f"你好,我是{self.name}") # 绑定到p1实例 p1.say_hello = types.MethodType(say_hello, p1) p1.say_hello() # 输出:你好,我是张三 # p2实例无此方法 # p2.say_hello() # 报错:AttributeError: 'Person' object has no attribute 'say_hello'
(2)动态新增类方法(影响所有实例)

python

# 定义类方法(第一个参数为cls) def get_class_name(cls): print(f"类名:{cls.__name__}") # 绑定为类方法 Person.get_class_name = classmethod(get_class_name) # 类和所有实例都能调用 Person.get_class_name() # 输出:类名:Person p1.get_class_name() # 输出:类名:Person p2.get_class_name() # 输出:类名:Person
(3)动态新增静态方法(无 self/cls 参数)

python

# 定义静态方法 def print_info(): print("这是Person类的静态方法") # 绑定为静态方法 Person.print_info = staticmethod(print_info) # 类和实例都能调用 Person.print_info() # 输出:这是Person类的静态方法 p1.print_info() # 输出:这是Person类的静态方法

3.3 注意事项

  • 动态新增的属性 / 方法仅在运行时生效,代码可读性会降低(建议仅在特殊场景使用,如动态扩展功能);
  • 实例方法仅绑定到当前实例,类方法 / 静态方法绑定到类,影响所有实例;
  • 可通过del关键字删除动态新增的属性 / 方法(如del p1.agedel Person.print_info)。

总结

关键点回顾

  1. 迭代器与生成器
    • 迭代器是实现__iter__()/__next__()的对象,核心是「惰性计算」;
    • 生成器是简化版迭代器,用yield实现,代码更简洁,优先使用生成器而非手动写迭代器;
    • 两者都适合处理大数据集,节省内存。
  2. 动态新增属性 / 方法
    • 实例属性仅影响当前实例,类属性 / 方法影响所有实例;
    • 实例方法需用types.MethodType绑定,类方法 / 静态方法需用classmethod/staticmethod装饰;
    • 体现 Python 动态语言特性,但需注意代码可维护性。
  3. 核心关联:生成器本质是迭代器,无需手动实现迭代器协议;动态特性可用于给迭代器 / 生成器类动态扩展功能。

这些特性是 Python 的核心优势,迭代器 / 生成器适合高性能数据处理,动态属性 / 方法适合灵活的功能扩展,掌握后能大幅提升代码的灵活性和效率。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/27 1:44:21

5分钟原型:自动修复JAVA符号错误工具

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 构建一个最小可行产品(MVP)&#xff0c;能够&#xff1a;1) 接收用户粘贴的含错误JAVA代码 2) 使用Kimi-K2模型分析找不到符号错误 3) 自动生成修复后的代码 4) 显示修改差异。要求…

作者头像 李华
网站建设 2026/4/3 2:58:04

零基础图解:麒麟系统安装保姆级AI指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个面向新手的麒麟系统安装指导应用。功能要点&#xff1a;1.步骤分解式交互引导 2.实时错误检测与解决 3.可视化安装进度 4.硬件自动检测 5.一键求助功能。使用图形化界面&a…

作者头像 李华
网站建设 2026/3/27 6:57:40

LLaMA Factory模型解释性:让你的AI决策不再是个黑箱

LLaMA Factory模型解释性&#xff1a;让你的AI决策不再是个黑箱 为什么我们需要可解释的AI模型&#xff1f; 在医疗AI项目中&#xff0c;向监管机构证明模型的决策依据是合规的必要条件。然而&#xff0c;大模型往往被视为"黑箱"&#xff0c;其内部决策过程难以追溯。…

作者头像 李华
网站建设 2026/3/25 18:53:08

ProxyCat代理池终极指南:从入门到精通

ProxyCat代理池终极指南&#xff1a;从入门到精通 【免费下载链接】ProxyCat 一款部署于云端或本地的代理池中间件&#xff0c;可将静态代理IP灵活运用成隧道IP&#xff0c;提供固定请求地址&#xff0c;一次部署终身使用 项目地址: https://gitcode.com/honmashironeko/Prox…

作者头像 李华
网站建设 2026/4/6 2:27:15

Whisper语音识别:3个步骤实现本地高效语音转文字

Whisper语音识别&#xff1a;3个步骤实现本地高效语音转文字 【免费下载链接】whisper-base.en 项目地址: https://ai.gitcode.com/hf_mirrors/openai/whisper-base.en 想要在个人设备上实现专业级的语音识别功能吗&#xff1f;OpenAI Whisper作为当前最先进的语音转文…

作者头像 李华