Python 从入门到秃顶 - 3
- coding
- python
- way2bald
高阶函数
高阶函数,High-order Function,指能接受其他函数作为参数的函数。
Python 中函数名相当于变量,指向函数本身。
def foo(content):
print(content)
f = foo
f('reinhardt') # 'reinhardt'
def foo(content):
print(content)
def bar(x, y, f):
f(x, y)
bar('hi', 'genji', foo) # 'hi genji'
- map
map
操作是对 Iterable 的每个元素进行变换,然后返回一个已经变换后的 Iterator:
def trans(x):
return x * 2
my_list = list(range(11))
my_list_mapped = map(trans, my_list)
print(list(my_list)) # 由于 Iterator 是惰性的,需要使用 list 函数将整个数列计算出来
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
- reduce
reduce
操作是对 Iterable 的每个参数进行变换,并且将累积上一个值并返回给下一步操作:
from functools import reduce
def sum_up(x, y): # x 是前一个返回值,y 是当前值
return x + y
my_list = list(range(6))
my_list_reduced = reduce(sum_up, my_list)
print(list(my_list_reduced)) #15
reduce
操作有拍平的效果,即降维的作用。比如上面将一个数组(二维)变换成一个整数(一维),相应地,使用 reduce
操作,也能将三维数组变换为二维数组。
- filter
filter
操作,顾名思义是用来过滤元素的:
def is_odd(x):
return x % 2 == 0
my_list = list(range(6))
my_list_filtered = filter(is_odd, my_list)
print(list(my_list_filtered)) # [0, 2, 4]
返回函数
def sum_up(*args):
def inner():
sum = 0
for n in args:
sum += n
return sum
return inner
f = sumup(1, 2, 3)
f() # 6
lambda 表达式
lambda 表达式用以声明匿名函数,可以简化代码,但是只能有一个表达式。
my_list = list(range(6))
my_list_filtered = filter(lambda x: x % 2 == 0, my_list)
lambda 表达式同样可以作为返回值让函数返回一个参数:
def return_lambda(x, y):
return lambda: x + y
# 相当于
def return_lambda(x, y):
def inner():
return x + y
return inner
def return_lambda1(x, y):
return lambda p, q: p + x, q + y
# 相当于
def return_lambda1(x, y):
def inner(p, q):
return p + x, q + y
return inner
装饰器
在代码运行期间动态增加函数功能的方式,称为装饰器(Decorator)。
每个函数都能使用 f.__name__
来获得其名字,我们想要在每个函数调用前打印出该函数的名字,但又不想改动现有的函数内部实现,可以使用装饰器:
# 声明装饰器
def decorator(func):
def inner():
print("call", func.__name__)
return func()
return inner
@decorator
def foo():
print('hello')
foo()
# call foo
# hello
可以看到,在装饰器里面,将被装饰的函数作为参数传入,然后在返回一个 inner
函数,inner
里面放入自行加入的逻辑(如打印出函数名),然后执行被装饰的函数,并且返回其返回值,最后返回 inner
函数。
所以,使用了 decorator
装饰的 foo
执行时相当于:
decorator(foo)
那么问题来了,如果被装饰的函数是有参的呢?而且参数我们不知道有多少个呢?这里提供一种通用的做法:
def decorator(func):
def inner(*args, **kw):
print("call", func.__name__)
return func(*args, **kw)
return inner
@decorator
def foo(x):
print(x)
foo('hello')
# call foo
# hello
如果装饰器本身需要传入参数,比如 @decorator(content)
,那么装饰器的声明需要再包裹一层:
def decorator_0(content):
def wrapper(func):
def inner(*args, **kw):
print(content, func.__name__)
return func(*args, **kw)
return inner
return wrapper
@decorator('hello')
def foo(x):
print(x)
foo('hi')
# hello foo
# hi
这样,我们就能在函数调用之前打印我们需要的东西而不改动原有的函数了。