高级函数(选修)
高级函数
在 Python 中,函数是一种基本类型的对象,这意味着可以将函数作为参数传给另一个函数。
将函数作为字典的值储存,将函数作为另一个函数的返回值:
def square(x):
"""Square of x."""
return x * x
def cube(x):
"""Cube of x."""
return x * x * x
# 函数的作为字典的值
funcs = {'square': square, 'cube': cube, }
x = 2
for func in sorted(funcs):
print(func, funcs[func](x))
func
funcs
函数参数
引用传递
传递给函数 f 的是一个指向 x 所包含内容的引用, 如果我们修改了这个引用所指向内容的值(例如 x[0]=999), 那么外面的 x 的值也会被改变:
def mod_f(x):
x[0] = 999
return x
x = [1, 2, 3]
x # [1, 2, 3]
mod_f(x) # [999, 2, 3]
x # [999, 2, 3]
过如果我们在函数中赋给 x 一个新的值(例如另一个列表),
那么在函数外面的 x 的值不会改变:
def no_mod_f(x):
x = [4, 5, 6]
return x
x = [1, 2, 3]
print(x)
print(mod_f(x))
print(x)
# [1, 2, 3]
# [999, 2, 3]
# [999, 2, 3]
高阶函数
以函数作为参数,或者返回一个函数的函数是高阶函数, 常用的例子有 map 和 filter 函数
map(f, sq) 函数将 f 作用到 sq 的每个元素上去,并返回结果组成的列表,
相当于:[f(s) for s in sq]
map(square, range(5)) # [0, 1, 4, 9, 16]
# 外面套个list,强转为list类型,是为了打印出函数的值
list(map(square, range(5)))
def is_even(x):
return x % 2 == 0
list(filter(is_even, range(5))) # [0, 2, 4]
list(map(square, filter(is_even, range(5)))) # [0, 4, 16]
reduce(f, sq) 函数接受一个二元操作函数 f(x,y), 并对于序列 sq 每次合并两个元素:
from functools import reduce
def my_add(x, y):
return x + y
reduce(my_add, [1, 2, 3])
返回一个函数:
def get_logger_func(target):
def write_logger(data):
with open(target, 'a') as f:
f.write(data + '\n')
return write_logger
fun_logger = get_logger_func('foo.txt')
fun_logger('hello')
# 查看foo.txt 是否生成
import os
os.path.exists('foo.txt')
匿名函数lambda
list(map(square, range(5)))
# 用匿名函数替换为:
list(map(lambda x: x * x, range(5)))
匿名函数虽然写起来比较方便(省去了定义函数的烦恼), 但是有时候会比较难于阅读:
s1 = reduce(lambda x, y: x + y, map(lambda x: x ** 2, range(1, 3)))
print(s1) # 5
# 简单的写法:
s2 = sum(x ** 2 for x in range(1, 3))
print(s2) # 5
global 变量
要在函数中修改全局变量的值,需要加上 global 关键字:
x = 15
def print_newx():
global x
x = 18
print(x)
print_newx()
print(x)
# 18
# 18
如果不加上这句 global 那么全局变量的值不会改变:
x = 15
def print_newx2():
x = 18
print(x)
print_newx2()
print(x)
# 18
# 15
递归
一般对于分治法,要用递归,不过在python中不怎么用,更高效的处理非波切利算法:
def fib(n):
"""Fib without recursion."""
a, b = 0, 1
for i in range(1, n + 1):
a, b = b, a + b
return b
print([fib(i) for i in range(10)])