上一篇中摘录了第一章中比较重要的句子或者令人可以思考的几句话。
这一遍在看完第一章后打算做一个总结,并完成中间的所有代码。
首先,开篇介绍了的计算机科学(CS)的发展。
SICP这门课的语言有scheme换成python后,伯克利便用python来完成这门课,因此接下来介绍了python的一些特性和参考文档(官网),不在详述。
在这一段中最重要的话无关任何语言。
(1)调试的原则:增量测试,缩小错误范围,检查假设,询问他人。
(2)增量测试,模块设计,精确的假设和团队合作贯穿整个计算机科学生涯。
接下来讲到程序的元素:原语表达式和语句,组合方法,抽象方法。
这一小结最重要的是变量与其环境。,引申到计算嵌套的表达式。
from math import sqrt, exp
from operator import add, mul, sub
print(mul(add(2, mul(4, 6)), add(3, 5)))
# 208
后面简单介绍了函数图表。python中的一切都是对象,并举例说明print是一个None值。
>>>two = print(2)
2
>>>print(two)
None
接下来的讲如何定义新的函数:
def <name>(<formal parameters>):
return <return expression>
第二行必须有缩进。此外,应注意到函数执行的环境。(本书将环境分为first frame, second frame……)
然后是调用自定义的函数,本函数有一个local frame, 只有本函数的变量可以访问。举例说明如下:
from math import sqrt, exp
from operator import add, mul, sub
def square(x):
return mul(x, x)
def sum_square(x, y):
return add(square(x), square(y))
print(sum_square(3,4))
# 25
仔细分析函数执行过程中调用的每一步,并清楚局部变量和全局变量的区别。
接着给了使用向导,选择名字。
函数名应该小写,并以下划线分隔,起到描述函数作用的目的。
函数名应该是函数体执行操作的翻译。
参数名小写,下划线分隔,并尽量用single-word,并尤其该有的意义。
接下来介绍了函数的艺术性。(函数是程序必不可少的部分)
原则:每个函数必须有确切的作用,不要做重复的工作(Don’t repeat yourself is a central tenet of software engineering),函数功能应该定义的简单一些。
文档注释(docstrings):
def pressure(v, t, n):
"""Compute the pressure in pascals of an ideal gas.
Applies the ideal gas law: http://en.wikipedia.org/wiki/Ideal_gas_law
v-- volume of gas, in cubic meters
t -- absolute temperature in degrees kelvin
n -- particles of gas
"""
k = 1.38e-23 # Boltzmann’s constant
return n * k * t / v
print(help(pressure))
第一行描述函数的功能,接下来描述参数和说明在函数中的作用。
当遇到help(pressure)的时候会打印出这些注释,方便自己和他人阅读程序。
缺省参数值:当函数值过多时,难以阅读。python提供默认参数值。
下面讲到了控制:
复合语句:函数就是复合语句
函数的局部赋值:
条件语句:介绍了三个布尔操作符,and, or ,not。
迭代:
def fib(n):
"""cumpute the nth Fibonacci number, for n >= 2"""
pred, curr = 0, 1
k = 2
while k < n:
pred, curr = curr, pred + curr
k = k + 1
return curr
print(fib(8))
# 13
下面讲到比较重要的一点,测试。
assert: assert fib(8) == 2(报错)
当语句执行正确,无效果。错误时报错并终止程序的执行。
Traceback <most recent call last>
File "1.py", line 12 in <module>
assert fib(8) == 2
AssertioError
文档测试:见前一篇截图介绍。
本章最后以及最重要的一节:高阶函数。
函数作为参数:
# 函数模板
def summation(n, term, next):
total, k = 0, 1
while k <= n:
total, k = total + term(k), next(k)
return total
# 计算cube和
def cube(k):
return pow(k, 3)
def successor(k):
return k + 1
def sum_cubes(n):
return summation(n, cube, successor)
print(sum_cubes(3))
# 36
# 计算整数和
def identity(k):
return k
def sum_natural(n):
return summation(n, identity, successor)
print(sum_natural(10))
# 55
函数作为一般方法:黄金比例
from math import sqrt, exp
from operator import add, mul, sub
def suqare(x):
return mul(x,x)
def successor(x):
return x + 1
def iter_improve(update, test, guess = 1):
while not test(guess):
guess = update(guess)
return guess
def near(x, f, g):
return approx_eq(f(x), g(x))
def approx_eq(x, y, tolerance = 0.001):
return abs(x - y) < tolerance
def golden_update(guess):
return 1/guess + 1
def golden_test(guess):
return near(guess, suqare, successor)
print(iter_improve(golden_update,golden_test))
接着介绍了嵌套定义:
from math import sqrt, exp
from operator import add, mul, sub
def suqare(x):
return mul(x,x)
def successor(x):
return x + 1
def approx_eq(x, y, tolerance = 0.001):
return abs(x - y) < tolerance
def iter_improve(update, test, guess = 1):
while not test(guess):
guess = update(guess)
return guess
def average(x, y):
return (x + y) / 2
def sqrt_update(guess, x):
return average(guess,x/guess)
def square_root(x):
def update(guess):
return average(guess, x/guess)
def test(guess):
return approx_eq(suqare(guess), x)
return iter_improve(update,test)
print(square_root(256))
函数作为返回值:
from math import sqrt, exp
from operator import add, mul, sub
def suqare(x):
return mul(x,x)
def successor(x):
return x + 1
def composel(f, g):
def h(x):
return f(g(x))
return h
add_on_and_square = composel(suqare,successor)
print(add_on_and_square(12))
# 169
接着介绍了lambda表示式:
lambda x : f(g(x))
“a function takes x and return f(g(x))”
上面的函数也可以写成:
composel = lambda f,g: lambda x : f(g(x))
最后通过一个例子(牛顿方法)来结束本章。
from math import sqrt, exp
from operator import add, mul, sub
def suqare(x):
return mul(x,x)
def successor(x):
return x + 1
def approx_eq(x, y, tolerance = 0.0001):
return abs(x - y) < tolerance
def iter_improve(update, test, guess = 1):
while not test(guess):
guess = update(guess)
return guess
def square_root(a):
return find_root(lambda x: suqare(x) - a)
def logarithm(a, base = 2):
return find_root(lambda x: pow(base, x) - a)
def approx_derivative(f, x, delta = 0.0001):
df = f(x + delta) - f(x)
return df/delta
def newton_update(f):
def update(x):
return x - f(x) / approx_derivative(f, x)
return update
def find_root(f, initial_guess = 10):
def test(x):
return approx_eq(f(x),0)
return iter_improve(newton_update(f), test, initial_guess)
print(square_root(16))
print(logarithm(32,2))
最后介绍了一点函数修饰符:
def trace1(fn):
def wrapped(x):
print('-> ', fn, '(', x, ')')
return fn(x)
return wrapped
@trace1
def triple(x):
return 3 * x
# thsi decorator is equivalent to:
# def triple(x):
# return 3 * x
# triple = trace1(triple)
print(triple(12))
总结:作为第一章来说,后面的内容,尤其是高阶函数的部分不是那么好理解,但是非常重要。而作为函数式编程的重要开端,必须立刻弄懂它。至于函数修饰符和单元测试,目前阶段可能还用的比较少。