we choose to go to t|

上山砍大树

园龄:5年3个月粉丝:13关注:3

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 function original_function as an argument.

The return value of make_averaged is a function that takes in the same number of arguments as original_function. When we call this returned function on the arguments, it will return the average value of repeatedly calling original_function on the arguments passed in.

Specifically, this function should call original_function a total of samples_count times and return the average of the results of these calls.

问题解析

这个问题其实很简单。make_averaged函数接受两个参数:

  1. original_function:接受n个参数,返回一个值
  2. samples_count:重复调用函数A的次数

接受了两个入参后,返回一个函数(高阶函数,将函数作为返回值)。这个函数接受的参数与original_function接受的参数相同。调用这个新函数的时候,会返回重复调用samples_countoriginal_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_countoriginal_function的值,那么就先看看在这里调用一次original_function的效果,然后看看重复调用samples_count的效果。

  1. roll_dice(2, dice):这个函数就是make_averaged参数1。这个函数投掷两次骰子,然后算总和。例如第一次投掷两枚骰子,结果分别为3和1,符合“sow sad”原则,所以这次结果为1。
  2. 重复调用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。

总结

  1. 请读源码:调用函数解决问题前,需要详细理解每一个函数到底做了什么。
  2. 遇到问题:那肯定是你代码没弄明白又或者是出现了bug,请再次重新回顾代码,做到详尽理解和测试。
  3. 偷懒被教育: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.也懒得理解,最终导致了让我跌了个跟头。而这个坑又是自信的我亲手埋下的。

本文作者:上山砍大树

本文链接:https://www.cnblogs.com/shangshankandashu/articles/18021986

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   上山砍大树  阅读(87)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起