def time4(chars): # 1. 这是一个【生成器函数】 for x in chars: # 2. 这是一个【普通循环】,遍历字符串 yield x * 4 # 3. 【核心】yield 让函数变成了生成器 t2 = time4("abcd") # 4. t2 是一个【生成器对象】(也是迭代器) for i in t2: # 5. 这是一个【普通循环】,作为消费者驱动 t2 print(i)
不觉得两个for循环很怪吗?
当 Python 解释器遇到 def time4(chars): 把代码块编译成底层的字节码(Bytecode),在内存中创建一个函数对象(Function Object),这个函数对象内部包含了一个非常重要的属性,叫做 __code__,并把它绑定到 time4 这个变量上,生成的 __code__ 对象里有一个非常关键的属性,叫做 co_flags(Code Flags,代码标志位,生成器yield)。
当你写下 t2 = time4("abcd") 时,解释器发现 time4 是一个包含 yield 的函数,解释器在内存中分配一块空间,创建一个生成器对象
调用 time4() 时:Python 检查 co_flags,发现它是生成器,于是不执行函数体,而是直接创建一个生成器对象。
调用 next() 时:Python 虚拟机开始逐行执行字节码,直到遇到 YIELD_VALUE,暂停并返回值。
所以外部调用时得到生成器,外部for循环接着将生成器iter成迭代器,内部for循环是个普通的迭代器,iter(chars)