日拱一卒,伯克利CS61A,两道题熟悉Python函数式编程
作者 | 梁唐
大家好,日拱一卒,我是梁唐。
我们今天继续来看伯克利CS61A的公开课,这次咱们聊聊hw02,也就是作业2。
这一次的作业关于Python函数式编程,其实哪怕是局限在Python语言当中,函数式编程也不是一个简单的概念。除了高阶函数之外,还有装饰器、偏函数、MapReduce等等许多内容。
但在日常使用当中,高阶函数的使用往往可以大幅提升代码质量,降低阅读难度,但大多数情况下并不是必须的。我不确定制定课程的教授是如何思考的,以我个人来看,作为初学者而言,了解函数式编程的思想以及它的使用场景,对这个概念熟悉起来,其实要比死记硬背一些所谓高端的用法更有用。
这一次的作业,刚好是一个非常好的用来学习、熟悉函数式编程思想的例子。
废话不多说,我们来看题。
首先,题目给定了一些代码,定义了一些函数。有常规函数,也有匿名函数。
def square(x):
return x * x
def identity(x):
return x
triple = lambda x: 3 * x
increment = lambda x: x + 1
add = lambda x, y: x + y
mul = lambda x, y: x * y
在Python当中,匿名函数以关键字lambda
开头,后面跟函数的传参,冒号之后是函数的返回结果。在这种格式的限定下,使得匿名函数的逻辑往往不能太过复杂,只能用来解决一些简单的计算问题。
我们简单阅读一下代码,可以看到这几个函数的功能都非常简单。square
是平方,identity
就是返回本身,triple
是乘3,increatment
是自增1,add
是两数相加,mul
是两数相乘。
看完了这段代码之后,开始正式看题。
Q1: Product
课件当中有一个例子是函数summation(n, term)
,它是一个高阶函数,它返回term(1) + term(2) +...+ term(m)
的结果。
请你仿照summation
函数,实现一个product
函数,来实现term(1) * term(2) *...*term(n)
。
其中课件中的summation
函数代码如下:
def summation(n, term):
"""Sum the first N terms of a sequence.
>>> summation(5, cube)
225
"""
total, k = 0, 1
while k <= n:
total, k = total + term(k), k + 1
return total
核心点在于term
不仅是函数的传参,而且它本身就是一个可以调用的函数。所以只要搞清楚这点,代码非常好写:
def product(n, term):
"""Return the product of the first n terms in a sequence.
n -- a positive integer
term -- a function that takes one argument
>>> product(3, identity) # 1 * 2 * 3
6
>>> product(5, identity) # 1 * 2 * 3 * 4 * 5
120
>>> product(3, square) # 1^2 * 2^2 * 3^2
36
>>> product(5, square) # 1^2 * 2^2 * 3^2 * 4^2 * 5^2
14400
>>> product(3, increment) # (1+1) * (2+1) * (3+1)
24
>>> product(3, triple) # 1*3 * 2*3 * 3*3
162
"""
"*** YOUR CODE HERE ***"
ret = 1
for i in range(1, n+1):
ret *= term(i)
return ret
# The identity function, defined using a lambda expression!
identity = lambda k: k
我们仿照同样的逻辑,将加好改成乘号即可。
第二个问题是使用product
函数实现阶乘函数factorial
。
def factorial(n):
"""Return n factorial for n >= 0 by calling product.
>>> factorial(4)
24
>>> factorial(6)
720
>>> from construct_check import check
>>> check(HW_SOURCE_FILE, 'factorial', ['Recursion', 'For', 'While'])
True
"""
"*** YOUR CODE HERE ***"
return product(n, identity)
我们只需要依照逻辑,让n个整数依次相乘即可。我们可以传入函数identity
,因为identity(x)=x
。
Q2: Make Adder with a Lambda
实现make_adder
函数,它返回一个lambda
表达式。
本题就是lambda
表达式的基本使用,了解函数式编程之后,也很简单。
def make_adder(n):
"""Return a function that takes an argument K and returns N + K.
>>> add_three = make_adder(3)
>>> add_three(1) + add_three(2)
9
>>> make_adder(1)(2)
3
"""
"*** YOUR CODE HERE ***"
return lambda x: x + n
对于返回的函数lambda x: x+n
而言,这里的参数n的定义在它的外部。这里涉及到Python当中一个很重要的概念叫做——闭包,闭包的原理和应用也是函数式编程中的一个范畴。
大家要是感兴趣可以去研究一下,这里不做过多的展开了。
本次作业的代码已经上传到了GitHub,可以点击【阅读原文】跳转,最后感谢大家的阅读。
喜欢本文的话不要忘记三连~