python-DAY10
函数使用进阶
Python 中的函数是“一等函数”,所谓“一等函数”指的就是函数可以赋值给变量,函数可以作为函数的参数,函数也可以作为函数的返回值。把一个函数作为其他函数的参数或返回值的用法,我们通常称之为“高阶函数”。
高阶函数
设计一个函数,传入任意多个参数,对其中int类型或float类型的元素实现求和操作。
def calc(*args, **kwargs):
items = list(args) + list(kwargs.values())
result = 0
for item in items:
if type(item) in (int, float):
result += item
return result
如果我们希望上面的calc函数不仅仅可以做多个参数的求和,还可以实现更多的甚至是自定义的二元运算
def calc(init_value, op_func, *args, **kwargs):
items = list(args) + list(kwargs.values())
result = init_value
for item in items:
if type(item) in (int, float):
result = op_func(result, item)
return result
注意,上面的函数增加了两个参数,其中init_value代表运算的初始值,op_func代表二元运算函数,为了调用修改后的函数,我们先定义做加法和乘法运算的函数,代码如下所示。
def add(x, y):
return x + y
def mul(x, y):
return x * y
如果要做求和的运算,我们可以按照下面的方式调用calc函数。
print(calc(0, add, 1, 2, 3, 4, 5)) # 15
如果要做求乘积运算,我们可以按照下面的方式调用calc函数。
print(calc(1, mul, 1, 2, 3, 4, 5)) # 120
上面的calc函数通过将运算符变成函数的参数,实现了跟加法运算的解耦合,这是一种非常高明和实用的编程技巧,但对于最初学者来说可能会觉得难以理解,建议大家细品一下。需要注意上面的代码中,将函数作为参数传入其他函数和直接调用函数是有显著的区别的,调用函数需要在函数名后面跟上圆括号,而把函数作为参数时只需要函数名即可**。
如果我们没有提前定义好add和mul函数,也可以使用 Python 标准库中的operator模块提供的add和mul函数,它们分别代表了做加法和做乘法的二元运算,我们拿过来直接使用即可。
import operator
print(calc(0, operator.add, 1, 2, 3, 4, 5)) # 15
print(calc(1, operator.mul, 1, 2, 3, 4, 5)) # 120
Python 内置函数中有不少高阶函数,我们前面提到过的filter和map函数就是高阶函数,前者可以实现对序列中元素的过滤,后者可以实现对序列中元素的映射。
我们要去掉一个整数列表中的奇数,并对所有的偶数求平方得到一个新的列表,就可以直接使用这两个函数来做到。
def is_even(num):
"""判断num是不是偶数"""
return num % 2 == 0
def square(num):
"""求平方"""
return num ** 2
old_nums = [35, 12, 8, 99, 60, 52]
new_nums = list(map(square, filter(is_even, old_nums)))
print(new_nums) # [144, 64, 3600, 2704]
要完成上面代码的功能,也可以使用列表生成式,列表生成式的做法更为简单优雅。
old_nums = [35, 12, 8, 99, 60, 52]
new_nums = [num ** 2 for num in old_nums if num % 2 == 0]
print(new_nums) # [144, 64, 3600, 2704]
再来讨论一个内置函数sorted,它可以实现对容器型数据类型(如:列表、字典等)元素的排序。我们之前讲过list类型的sort方法,它实现了对列表元素的排序,sorted函数从功能上来讲跟列表的sort方法没有区别,但它会返回排序后的列表对象,而不是直接修改原来的列表,这一点我们称为函数的无副作用设计,也就是说调用函数除了产生返回值以外,不会对程序的状态或外部环境产生任何其他的影响。使用sorted函数排序时,可以通过高阶函数的形式自定义排序的规则。
old_strings = ['in', 'apple', 'zoo', 'waxberry', 'pear']
new_strings = sorted(old_strings)
print(new_strings) # ['apple', 'in', 'pear', waxberry', 'zoo']
上面的代码对大家来说并不陌生,但是如果希望根据字符串的长度而不是字母表顺序对列表元素排序,我们可以向sorted函数传入一个名为key的参数,将key参数赋值为获取字符串长度的函数len,这个函数我们在之前的课程中讲到过,代码如下所示。
old_strings = ['in', 'apple', 'zoo', 'waxberry', 'pear']
new_strings = sorted(old_strings, key=len)
print(new_strings) # ['in', 'zoo', 'pear', 'apple', 'waxberry']
说明:列表类型的
sort方法也有同样的key参数,有兴趣的读者可以自行尝试。