python阴(yin)阳(yang)谜题的分析

昨天正好把汉诺塔小游戏中的递归给写完了,链接:汉诺塔中的递归,然后在打草稿时忽然想起来以前在别个地方看到的关于 python阴阳谜题,代码在下面:

def yin(cb1):
    yield "@"
    def yang(cb2):
        yield "*"
        yield from cb1(cb2)
    yield from yang(yang)
ge = yin(yin)
for _ in range(100):
    print(next(ge))

输出结果如下:

@ * @ * * @ * * * @ * * * * @ * * * * * @ * * * * * * @ * * * * * * * @ * * * * * * * * @ * * * * * * * * * @ * * * * * * * * * * @ * * * * * * * * * * * @ * * * * * * * * * * * * @ * * * * * * * * * 

其中,yield是以一个迭代器 yield from也是一个迭代器
代码或者也有下面这个写法的

//来源于网络
def puzzle():
    def yin(yin):
        yield '@'
        def yang(yang):
            yield '*'
            yield from yin(yang)
        yield from yang(yang)
    yield from yin(yin)

for x, _ in zip(puzzle(), range(256)):
    print(x, end='')
print()

本质上是一样的,结果也一样,都是在每一个 @字符之间+1个递增 * 字符 。然后之前也是对着这个函数看了很久

错误的分析

第一次看到阴阳谜题时感觉应该挺简单,无非就是几个类似函数嵌套的迭代器嵌套罢了

正确的分析

  1. 时刻注意函数在调用时在内存中的地址,即所看到的函数名是不是真的所预想的那个函数
  2. 时刻注意传入的参数,因为参数 cb1 和 cb2 都是以函数为参数传入的,那么这个传入的函数名是不是真的所预想的那个函数

之前错误的分析就是太想当然,认为yang函数就一直是那个yang,认为yin函数就一直是那个yin(当然后面会发现,这个yin函数确实一直是yin函数),对于这个阴阳函数,最好的方式也是最容易理解的方式是通过断点辅助分析

def yin(cb1):
    yield "@"				//1 5 ...
    def yang(cb2):
        yield "*"			//3	7 ...
        yield from cb1(cb2)	//4	8 ...
    yield from yang(yang)	//2 6 ...

ge = yin(yin)
for _ in range(100):
    print(next(ge))
  1. 通过main函数的 yin(yin) 函数启动,启动 yin函数并且此时参数 cb1=yin,第一个next输出 @
  2. 启动 yang(yang)
  3. 此时参数cb2=yang,cb1=yin,并通过next输出 *
  4. 启动迭代器 yin(yang),❗❗❗此时的yang是通过cb2传入,即第二步的yang
  5. 启动yin(yang)之后,参数cb1变为yang,并通过next输出 @
  6. 启动 yang(yang),此时的 yang(yang)均为新的函数,即在内存中会新开辟一个空间,如果有兴(wu)趣(liao)的的可以尝试输出这个yang和第2步的yang函数的 id(yang) 地址,可以发现是不同的
  7. 此时参数cb1=yang(第2步生成的),参数cb2=yang(第6步生成的),并通过next输出 *
  8. 启动 yang(yang),这个yang函数(第2步生成的)又回到了之前yin函数的 “势力范围”,而此时此刻的参数 cb1=yin,cb2=yang(第6步生成的),所以此时又会重新启动 yin(yang)

再往下推几步就会发现,虽然第6步那个位置看起来在不停的循环启动 yang(yang) ,貌似进入了一个死循环,其实每一次重新进入 yang(yang)的时候,yang函数在不停的变化,不停的往回走,所以导致了

  1. yield from cb1(cb2)中的cb1不停的往上走,直到找到 yin函数重新开始…
  2. 找到 yin函数之后, 通过yield from cb1(cb2)传给yin的cb2一直是最新生成的yang

这里我没有使用调用函数这个描述,因为都是生成器,用启动可能更加恰当,理解的时候用“调用”也是可以的

结束语

因为之前也是一直在研究但是没研究出来,具体的,阴阳谜题和我今天看的汉诺塔递归函数里面的传参,有着相似的诡异之处。另外,阴阳谜题是不是递归实现的目前我真的还看不出来,也许有递归的东西在里面,但是即使是递归实现的,感觉上只有递出去,并没有收回来,请指正~

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值