本文目录
内容梳理
这里简单回忆&总结一下第一章的内容
1.1 引言
- 强调了计算机科学与抽象的联系。
- Python3的一些简介。
- Python(
编程语言)的基础概念: 语句与表达式、函数、对象、解释器 - 实践指南——基本的debug方法论。
1.2 编程元素
程序必须为人类阅读而编写,而仅仅是碰巧可以让机器执行。
每门强大的语言都应该拥有用于完成以下任务的机制:
- 基本的表达式与语句,由语言提供,表示最简单的构建代码块
- 表达式
- 调用表达式
- 库函数
- 表达式
- 组合的手段,组合简单的元素来构建复杂的元素。
- 嵌套表达式
- 求出运算符
- 求出操作数子表达式
- 在值为操作数子表达式的参数上调用值为运算符子表达式的函数
- 图解
- 嵌套函数
- 嵌套表达式
- 抽象的手段,通过抽象来命名复杂的元素,并将其作为一个整体操作。
- 名称与绑定
- 环境
- 解释器维护某些内存来跟踪这些名称和值的绑定
- 函数图解
- 自定义函数(1.3)
1.3 定义新的函数
- def语句
- 形参、实参
- python没有函数重载
- 环境
- 图解
- 帧
- 全局帧
- 局部帧与函数调用
- 命名规范——下划线而非驼峰
- 永远不要单独使用l(小写L)、O或者I(大写i)
- 函数名与参数名应该使用描述性的名称
- 函数式抽象
1.4 实践指南:函数的艺术
如何编写良好的函数
- 每个函数只应做一个任务,可以使用短小的名称来定义,一行文本来标识。
- 不要重复劳动(DRY),如果你在复制粘贴一段代码,可能你已经发现了一个使用函数抽象的机会。
- 函数应该定义的一般一些,并通过(默认)参数来特化它。
- 文档字符串
- 描述函数的任务&参数
- 参数默认值
1.5 控制
语句的值是不存在的,我们用执行而非求值来描述语句。表达式也可以作为语句执行,他们会被求值,但是他们的值会被舍弃。
- 复合语句
- 局部赋值(局部变量)
- 函数作用域
- 与控制语句结合,提高函数的表现力
- 将名称赋为间接量,理清复杂表达式的含义
- 条件语句
- 迭代语句
- 测试
- assert
- doctest
1.6 高阶函数
作为程序员,我们应该留意识别程序中低级抽象的机会,在它们之上构建并泛化它们来创建更加强大的抽象。
- 函数作为参数
- 函数作为一般方法
- 嵌套函数
- 词法作用域(定义时而非运行时)
- 关联环境
- 调用时局部帧扩展于关联环境
- 函数作为返回值
- 局部定义的函数返回时仍持有关联的环境(函数闭包)
- Lambda表达式
- lambda表达式中不允许出现赋值或控制语句
- 函数作为一等公民
- 带有最少限制的元素被称为具有一等地位
- 可以绑定到名称
- 可以作为参数传递
- 可以作为返回值返回
- 可以包含在数据结构中
- 函数装饰器
总结与感悟
环境图解
这是我第一次接触到用图形去解释一些编译的过程与原理,再加上书中对元素解释的也不是很清晰,看起来还是有点吃力的。但渐渐熟悉了之后,确实加强了对原理的理解。
python基础与抽象
可以明显感觉到,这本书讲述python的顺序与逻辑和别的教材不太一样。强调抽象贯穿了整个章节,比如强化函数的概念、强调隔离、在介绍控制语句和内置数据结构前介绍函数…
抽象可能是这本书提到次数最多的概念,也是最着重强调的概念。但是呢,编程终归是一项需要不断实践,在实践中深化认识的技能。还是需要在未来的编程实践中不断的强化自己的理解与认识捏!
python与函数式编程
本书对函数的强调以及python对函数、高阶函数的支持等一度让我以为python是一种函数式语言。
在查阅了一些参考资料之后发现,虽然python对于函数式编程有比较不错的支持,如函数一等公民的身份、高阶函数等等。但尾递归的优化、函数的克里化等问题,确实限制了函数式编程的优雅与效率。再加上Guido本人的看法,以及python使用者并没有大量的使用函数式编程,基本可以认为python可以采用函数式编程的范式,但并不是一种函数式语言。
考虑到python虽然万物皆对象,但len()等函数却不是以方法的形式存在的。再加上python可以用函数去模仿类,类的定义也显得有些别扭(对我来说总感觉很“函数”)。所以我个人感觉python还是更偏向命令式或者函数式吧…
项目——Hog
项目目标
在这个项目中,需要模拟骰子游戏Hog的逻辑并为它开发多种策略。这需要用到控制和高阶函数。
游戏规则
在Hog游戏中,两个玩家轮流行动争取首先达到100分。在每个回合中,当前的玩家选择一些骰子(最多10个)来掷出,他的得分是骰子结果的总和。
同时,游戏还要满足以下的规则:
- PigOut: 如果掷出1,则本轮得分为1分
- FreeBacon: 如果选择掷0颗骰子,则获得对手得分中最大的数字+1的分数。
- HogWild: 如果两个玩家的总分之和是7的倍数,那么当前玩家就会掷出四面骰,而非六面骰。
- SwineSwap: 如果在一个回合结束时,其中一个玩家的总分正好是另一个玩家的两倍,那么玩家就会交换总分。
项目框架
关键代码
这里展示了模拟一局游戏的逻辑,将函数作为参数的抽象能力是这部分的关键。
def play(strategy0, strategy1, goal=GOAL_SCORE):
"""Simulate a game and return the final scores of both players, with
Player 0's score first, and Player 1's score second.
A strategy is a function that takes two total scores as arguments
(the current player's score, and the opponent's score), and returns a
number of dice that the current player will roll this turn.
strategy0: The strategy function for Player 0, who plays first.
strategy1: The strategy function for Player 1, who plays second.
"""
who = 0 # Which player is about to take a turn, 0 (first) or 1 (second)
score, opponent_score = 0, 0
"*** YOUR CODE HERE ***"
while max(score, opponent_score) < goal:
# Hog Wild
dice_type = select_dice(score, opponent_score)
if who == 0:
# 对手的得分 FreeBacon
score += take_turn(strategy0(score, opponent_score), opponent_score, dice_type)
else:
opponent_score += take_turn(strategy1(opponent_score, score), score, dice_type)
who = other(who)
# Swine Swap
if 2 * score == opponent_score or opponent_score * 2 == score:
score, opponent_score = opponent_score, score
return score, opponent_score # You may wish to change this line.
项目结果
- 模拟游戏逻辑的部分完成了,并通过提供的GUI交互式的测试过。
- 游戏胜率评估的部分也完成了,这里用到了嵌套函数以及函数作为返回值。
- 游戏的基础策略完成了,包含了利用FreeBacon、SwineSwap等规则的策略。
- 最终的策略没有去做,主要还是时间问题。此外,感觉这部分主要是逻辑的问题,与函数抽象关系不大,所以就没去完成这一部分。
项目总结
这个小项目意在让人体会函数抽象。不得不感慨这种写好程序框架,把空位留出来,并且配有相当完善的文档的项目做起来是真的舒畅。
对于这个项目,首先感到的就还是逻辑复用吧,通过将名称与代码段相关联,可以多次复用同样的逻辑。
其次应该是高阶函数的使用了,有效的构造了几个一般函数,通过接受不同的函数参数来实现不同的功能。这种高阶抽象确实让我感受到了快感!
最后是一种隐含的功效吧,抽象带来的逻辑上的隔离。让我在思考问题的时候,有效的简化了心中的模型,将一部分功能简化为了特定输入输出的接口。怎么说呢,这种心智负担的减少,也是抽象带来的强大的表现力的体现吧!
以上。