Project 1: The Game of Hog--Problem 8 (2 pt)问题
在写def make_averaged(original_function, samples_count=1000):函数的时候,发现函数很容易实现,但是加入实际的情景就没法理解。现在在这里记录下自己遇到的问题:
Problem 8 (2 pt)问题描述
Implement
make_averaged, which is a higher-order function that takes a functionoriginal_functionas an argument.The return value of
make_averagedis a function that takes in the same number of arguments asoriginal_function. When we call this returned function on the arguments, it will return the average value of repeatedly callingoriginal_functionon the arguments passed in.Specifically, this function should call
original_functiona total ofsamples_counttimes and return the average of the results of these calls.
问题解析
这个问题其实很简单。make_averaged函数接受两个参数:
original_function:接受n个参数,返回一个值samples_count:重复调用函数A的次数
接受了两个入参后,返回一个函数(高阶函数,将函数作为返回值)。这个函数接受的参数与original_function接受的参数相同。调用这个新函数的时候,会返回重复调用samples_count次original_function的值。
疑问
但是在检测自己是否理解这个函数(python3 ok -q 08 -u)的选项中,对于这个问题我总是答错:
>>> from hog import *
>>> dice = make_test_dice(3, 1, 5, 6)
>>> averaged_roll_dice = make_averaged(roll_dice, 1000)
>>> # Average of calling roll_dice 1000 times
>>> # Enter a float (e.g. 1.0) instead of an integer
>>> averaged_roll_dice(2, dice)
?
在我理解中,dice被定义好后,每次调用dice就会指定下一个值,然后循环如此。(这个坑好久之前就被埋好了😒 )
roll_dice呢,就是一个函数,接收投掷总数和骰子类型,返回投多个骰子的总点数(遵循sow sad原则)。
那么既然说这个make_averaged函数是重复调用samples_count次original_function的值,那么就先看看在这里调用一次original_function的效果,然后看看重复调用samples_count的效果。
roll_dice(2, dice):这个函数就是make_averaged参数1。这个函数投掷两次骰子,然后算总和。例如第一次投掷两枚骰子,结果分别为3和1,符合“sow sad”原则,所以这次结果为1。- 重复调用
samples_count次的结果:这就是我卡住的地方,也是需要反思的地方。
解决思路
这里因为我并没有深入理解dice函数的机制,导致我并不理解重复调用dice到底有什么效果。下面贴上dice的代码,学习一下嵌套函数如何利用nonlocal将修改上一层函数的变量:
def make_test_dice(*outcomes):
"""Return a die that cycles deterministically through OUTCOMES.
>>> dice = make_test_dice(1, 2, 3)
>>> dice()
1
>>> dice()
2
>>> dice()
3
>>> dice()
1
>>> dice()
2
This function uses Python syntax/techniques not yet covered in this course.
The best way to understand it is by reading the documentation and examples.
"""
assert len(outcomes) > 0, 'You must supply outcomes to make_test_dice'
for o in outcomes:
assert type(o) == int and o >= 1, 'Outcome is not a positive integer'
index = len(outcomes) - 1
def dice():
nonlocal index
index = (index + 1) % len(outcomes)
return outcomes[index]
return dice
这里的dice()函数中,使用nonlocal index的声明,dice()可以修改make_test_dice的局部变量index。
这样代码就好理解了:
>>> dice = make_test_dice(3, 1, 5, 6)
dice每次调用的时候,都会改变make_test_dice的局部变量index。这样index就会循环往复地在[0, len(outcomes) - 1]中徘徊。
使用 nonlocal 关键字可以指示 Python 解释器在嵌套函数中查找并修改上一层函数的局部变量。
这样再去看roll_dice(2, dice)重复调用samples_count次的结果:第一次投掷两个骰子,结果分别为3和1,得分为1;第二次投掷两个骰子,结果分别为5和6,得分为11;第三次投掷两个骰子,结果分别为3和1,得分为1...
这样重复调用的结果就是1和11,重复1000次的平均值就是(1 * 500 +11 * 500) / 1000 = 6.0。
总结
- 请读源码:调用函数解决问题前,需要详细理解每一个函数到底做了什么。
- 遇到问题:那肯定是你代码没弄明白又或者是出现了bug,请再次重新回顾代码,做到详尽理解和测试。
- 偷懒被教育:
nonlocal关键字懒得查,注释This function uses Python syntax/techniques not yet covered in this course. The best way to understand it is by reading the documentation and examples.也懒得理解,最终导致了让我跌了个跟头。而这个坑又是自信的我亲手埋下的。

浙公网安备 33010602011771号