英文网站建设怎么收费,做任务领礼品的网站,dede网站打开慢,设计配色的网站一、问题起源#xff1a;
想象一下#xff0c;您掌握了一种魔法#xff0c;在代码世界里#xff0c;您可以轻松呼唤出一个整数。然而#xff0c;事情并不总是看起来那样简单。在Python的奇妙王国中#xff0c;我遇到了一个有趣的谜题#xff1a;
def tst():try:print(…一、问题起源
想象一下您掌握了一种魔法在代码世界里您可以轻松呼唤出一个整数。然而事情并不总是看起来那样简单。在Python的奇妙王国中我遇到了一个有趣的谜题
def tst():try:print(hello world)return 1except:yield 2
print(tst())
type(tst())表面上这段代码看起来像是在进行一个简单的问候和返回神秘数字1的仪式。但是执行后却揭晓了一个出乎意料的结果
generator object tst at 0x00000255F7E039F0
generator这个不是预期中的整数而是一种被称为生成器的强大生物。那么这是如何发生的呢
二、魔法解密为何它是生成器 一段代码的命运在Python领域里是由它出生定义的时刻就注定了。就像预言中说的函数的行为被它的定义方式固定下来而非仅仅由它实际运行时的动作决定。 Python中的先知们编译器在瞥见函数的定义时会使用他们的预言之眼分析功能寻找隐藏于代码深处的yield这个关键词符。发现了yield哪怕它藏在一条不曾通往的冷僻小径上逻辑上不可达的代码块编译器也会宣告这是一个生成器 一个神秘的转变即使您期待着回报返回值由于yield的存在被选中的函数会呈现出生成器的身姿并赋予它按需迭代、暂停和恢复的能力。 这是因为 Python 的函数定义的语义决定了在编译函数的时候解释器会如何处理它。 在 Python 中函数如何行为取决于函数的定义而不仅仅是实际运行时的行为。当 Python 的编译器遇到一个函数定义时它会检查函数体内的语句。如果它发现了 yield 关键字不管这个 yield 是否在逻辑上可达即不管它是否在 try 块还是 except 块或者它是否在某个条件判断很少为真的代码分支中它都会将这个函数标记为生成器函数。 这意味着一旦函数体中出现 yieldPython 就会创建生成器对象而不是直接执行函数体并返回单一的结果。 三、神秘仪式为何print未被宣读 这个生成器仪式的初次召唤首次调用函数并不意味着立即展现魔法执行函数体内的代码而是颁发一个神秘的标记生成器对象。这个标记好像是一个尚未开启的宝箱装载着即将展开的奇妙冒险。 迭代这个标记调用生成器对象的next()方法就像翻开宝箱的锁魔法函数体的代码才会启动直到遇到第一个yield魔法符表达式为止。 想要领略这段冒险就请看以下的仪式演示 def my_generator():print(开始执行)yield 1print(继续执行)yield 2print(执行结束)# 创建生成器对象
gen my_generator()# 开始迭代生成器
next(gen)
# 输出开始执行
# 在此时, 第一个 yield 1 表达式被执行, 并且函数的状态被暂停next(gen)
# 输出继续执行
# 在此时, 第二个 yield 2 表达式被执行, 并且函数的状态再次被暂停next(gen)
# 输出执行结束
# 函数执行到最后, 并且因为没有更多的 yield 表达式迭代到此结束
# 如果试图继续迭代将抛出 StopIteration 异常。这是因为生成器函数在首次被调用并返回生成器对象时并不会执行任何函数体内部的代码它只是返回一个生成器对象。这个生成器对象可以理解为一个有待执行的函数体。只有当你开始迭代这个生成器即调用该生成器对象的 next() 方法时生成器函数的代码才会开始执行直到遇到第一个 yield 表达 四、最终揭示
即使很隐秘yield魔法符号的存在会让一个函数被赋予生成器的身份。魔法的初次召唤生成器函数首次调用仅仅是交付了一个未来冒险的符记生成器对象不触发任何神秘力量不执行函数体内的代码。开启这个冒险使用next()方法迭代生成器对象才真正激活了仪式中的法术函数体内的代码并把我们引领至第一个法术停顿点yield。