本节知识点:Python中函数是first-class object 与 nest-function定义
题目简述
Define a function cycle that takes in three functions f1, f2, f3, as arguments. cycle will return another function that should take in an integer argument n and return another function. That final function should take in an argument x and cycle through applying f1, f2, and f3 to x, depending on what n was. Here's the what the final function should do to x for a few values of n:
n = 0, return x n = 1, apply f1 to x, or return f1(x) n = 2, apply f1 to x and then f2 to the result of that, or return f2(f1(x)) n = 3, apply f1 to x, f2 to the result of applying f1, and then f3 to the result of applying f2, or f3(f2(f1(x))) n = 4, start the cycle again applying f1, then f2, then f3, then f1 again, or f1(f3(f2(f1(x)))) And so forth.
Hint: most of the work goes inside the most nested function.
代码规范
def cycle(f1, f2, f3):
""" Returns a function that is itself a higher order function
pass
测试用例
def add1(x):
return x + 1
def times2(x):
return x * 2
def add3(x):
return x + 3
my_cycle = cycle(add1, times2, add3)
identity = my_cycle(0)
identity(5)
5
add_one_then_double = my_cycle(2)
add_one_then_double(1)
4
do_all_functions = my_cycle(3)
do_all_functions(2)
9
do_more_than_a_cycle = my_cycle(4)
do_more_than_a_cycle(2)
10
do_two_cycles = my_cycle(6)
do_two_cycles(1)
19
问题剖析
notes:题目是英文的,我简要翻译一下,相信大家看用例也能明白
定义函数cycle,其输入参数为f1, f2 ,f3,返回值为一个函数 (不妨记为func)
func函数的输入参数为n,其返回值为一个函数(不妨记为 func_inner)
func_inner的输入参数为x,返回值为一个数值(不妨记为result)
result的值依据f1,f2,f3和n的值而定
n = 0, 返回 x
n = 1, 返回 f1(x)
n = 2, 返回 f2(f1(x))
n = 3, 返回 f3(f2(f1(x)))
n = 4, 返回 f1(f3(f2(f1(x))))
依次类推 ……
这个题目的知识点在于两个:(1)Python中函数是first-class object,可以作为arguments,同时也可以构成return 返回值;(2)利用函数嵌套进行定义,内部定义的函数作为外部函数的返回值
Solution 1 code
基准测试函数定义
def add1(x):
return x + 1
def times2(x):
return x * 2
def add3(x):
return x + 3
cycle函数定义
def cycle(f1, f2, f3):
def func(n):
def func_inner(x):
f = lambda x: f3(f2(f1(x)))
if n == 0:
return x
elif n % 3 == 1:
if n <= 3:
return f1(x)
int_n, fac_n = divmod(n, 3)
result = f(x)
for i in range(int_n - 1):
result = f(result)
return f1(result)
elif n % 3 == 2:
if n <= 3:
return f2(f1(x))
int_n, fac_n = divmod(n, 3)
result = f(x)
for i in range(int_n - 1):
result = f(result)
return f2(f1(result))
elif n % 3 == 0:
int_n, fac_n = divmod(n, 3)
result = f(x)
for i in range(int_n - 1):
result = f(result)
return result
return func_inner
return func
my_cycle = cycle(add1, times2, add3)
代码结果测试
print("test1: " , my_cycle(0)(5) )
print("test2: " , my_cycle(2)(1) )
print("test3: " , my_cycle(3)(2) )
print("test4: " , my_cycle(4)(2) )
print("test5: " , my_cycle(6)(1) )
test1: 5
test2: 4
test3: 9
test4: 10
test5: 19
Solution 2 code
基准测试函数定义
def add1(x):
return x + 1
def times2(x):
return x * 2
def add3(x):
return x + 3
cycle函数定义
def cycle(f1, f2, f3):
def func(n):
def func_inner(x):
i = 0
while i if i % 3 == 0:
x = f1(x)
elif i % 3 == 1:
x = f2(x)
else:
x = f3(x)
i += 1
return x
return func_inner
return func
代码结果测试
print("test1: " , my_cycle(0)(5) )
print("test2: " , my_cycle(2)(1) )
print("test3: " , my_cycle(3)(2) )
print("test4: " , my_cycle(4)(2) )
print("test5: " , my_cycle(6)(1) )
test1: 5
test2: 4
test3: 9
test4: 10
test5: 19
代码分析
第一个code我写的,第二个code另外一个大牛写的,基本架构差不多
def cycle(f1, f2, f3):
def func(n):
def func_inner(x):
pass
return func_inner
return func
这也是解题的基本思路:Python中function为first-class objec,可以作为返回值;同时,利用函数嵌套进行定义,内部定义的函数作为外部函数的返回值
code的微妙之处在于 func_inner的定义
def func_inner(x):
f = lambda x: f3(f2(f1(x)))
if n == 0:
return x
elif n % 3 == 1:
if n <= 3:
return f1(x)
int_n, fac_n = divmod(n, 3)
result = f(x)
for i in range(int_n - 1):
result = f(result)
return f1(result)
elif n % 3 == 2:
if n <= 3:
return f2(f1(x))
int_n, fac_n = divmod(n, 3)
result = f(x)
for i in range(int_n - 1):
result = f(result)
return f2(f1(result))
elif n % 3 == 0:
int_n, fac_n = divmod(n, 3)
result = f(x)
for i in range(int_n - 1):
result = f(result)
return result
我写的code 吧 f3(f2(f1))作为一个loop,看这个lambda函数的定义
f = lambda x: f3(f2(f1(x)))
即可看出我的解决思路
再看看大牛的思路
def func_inner(x):
i = 0
while i if i % 3 == 0:
x = f1(x)
elif i % 3 == 1:
x = f2(x)
else:
x = f3(x)
i += 1
return x
大牛的loop建立在了f1、f2、f3之上,确地6,膜拜了。仔细看看大牛每个细节的处理
传入n为0,则直接返回x
大牛这段代码中 while i
n=1,结果为f1(x)
大牛将i初始值设置为0,故当 i % 3 == 0 时,进行f1(x)运算,随后i+=1,此时i为1,跳出循环,return的值为f1(x)
n=2,结果为f2(f1(x))
先进行 n=1的运算,注意此时x ← f1(x),随后i变为1;此时满足 i % 3 == 1,进行f2(x)的计算,等价于f2(f1( x最原始的值 ))
后面依次类推 ……
比较好设计在于这样子的分支设计
def func_inner(x):
i = 0
while i 分支1:
x = f1(x)
分支2:
x = f2(x)
分支3:
x = f3(x)
i += 1
return x
References
Motto
日拱一卒,功不唐捐
![7e5084559cc232103f77585a82cbcb9f.png](https://img-blog.csdnimg.cn/img_convert/7e5084559cc232103f77585a82cbcb9f.png)