|
|
发表于 2016-12-29 11:59:06
|
显示全部楼层
上面谈了数学模型,现在又来谈谈代码的实现
for result in make_change(amount-coin ,coins=coins,hand=hand+[coin]):
这是递归的入口最容易出问题,
在每一次拿数字的时候,是不能改变这个层级这个作用域里的变量值的
所以是用amount-coin和hand+[coin]把这个层级选的数字coin分别和amount和hand
组成公式传了下一个层级,并没有改变当前层级的hand和amount
这是这个递归的核心所在。
我们再来谈谈yield
当你开始执行for way in make_change(100,coins=[10,25,50]):
这句的时候函数开始运行,启动生成器
先取第一个10
在运行的第一圈就会直接进入函数的这句
for result in make_change(amount-coin ,coins=coins,hand=hand+[coin]):
这句又是启动一个生成器,最外围的第一圈是没有跑完的,
现在又进入下层
又取一个10
又启动生成器
进入下一层
直到取的数字大于50
函数又退回到上一层
由于每层都要选3个数字
所以每一层都还要再启动2次生成器
我再来谈第一次生成结果的时候
但【10,10,10,10,10】的时候
最下层的生成器会执行
if amount==0:
yield hand
这个结果会一次返回给每一个层级的出入口
for result in make_change(amount-coin ,coins=coins,hand=hand+[coin]):
yield result 这句不停的通过每一层yield result 传递直到最外层,最后传到函数外面
就是下面这句
for way in make_change(100,coins=[10,25,50]):
for 循环又启动下一次生成
又启动了,生成器厉害的地方就是,从原来的地方继续跑
然会生成器会通过
for result in make_change(amount-coin ,coins=coins,hand=hand+[coin]):
每一层的入口回到最下层的
yield hand这个刚才yield 【10,10,10,10,10】的地方
又开始继续
【10,10,10,10,10】由于等于50而不是小于50函数会继续试
在我发的树图中你会看的很清楚
【10,10,10,10,10】会进入下面语句分别和10,25,50组合
结果是都会大于50最后停止了是不会再进入下一个层级
由于这个层级的硬币都选完了,都大于50,什么都不会发生
就会继续进行上一层的选25这个【10,10,10,10】和25就会进入这个选择的下一层
在下一层中都会大于50就会终止,返回到【10,10,10,10】和50
【10,10,10,10】和50再进入下一层,结果大于50都回返回来
就再回到上一层把没选的数字,都试完,以此类推,所有代码就会执行完
只要遇到=50的时候
就会yield hand
再通过每一层的yield result,返回到最外面
再继续的时候,生成器又会回到最里面。继续进行 |
|