偏函数, 高阶函数, 返回函数, 匿名函数, 闭包
偏函数
当我们写一个参数比较多的函数时, 如果有些参数, 大部分场景下都是某一个固定值, 那么为了简化使用, 就可以创建一个新函数, 指定我们要使用的函数的某个参数为某个固定的值; 这个新函数就是"偏函数"
即: 在原有函数的基础上, 写一个新函数, 来简化这个函数的使用
例如: 此时有一个函数, 拥有四个参数
def aFunc(a, b, c, d=1):
print(a + b + c + d)
此时, 我们需要在大量地方使用这个函数, 但是d的值为2, 如果每次都要指定d, 是很麻烦的事, 所以我们再次创建一个函数
方式一: 写一个新函数, 指定
d=2
, 如下, 这样我们只需要调用bFunc
函数就可以了
def bFunc(a, b, c, d=2):
aFunc(a, b, c, d)
bFunc(1, 2, 3) # 打印: 8
- 方式二: 借助
functools
模块的partial
函数
bFunc = functools.partial(aFunc, d = 2)
bFunc(1, 2, 3) # 打印: 8
- 偏函数的一个应用场景
import functools
int2 = functools.partial(int, base=16)
result = int2("15")
print(result) # 打印: 21, 认为15是十六进制数, 转为十进制就是21
高阶函数
- 当一个函数A的参数, 接收的又是另一个函数时, 则把这个函数A称为是"高阶函数"
- 例如排序函数
sorted
temp = [{"name": "张三", "age" : 18}, {"name" : "李四", "age" : 20}, {"name" : "王五", "age" : 19}]
def value(x):
return x["age"]
result = sorted(temp, key=value)
print(result)
# 打印: [{'name': '张三', 'age': 18}, {'name': '王五', 'age': 19}, {'name': '李四', 'age': 20}]
- 上述代码中,
sorted
函数的参数key
接收的是另一个参数temp
, 所以sorted就是高阶函数
返回函数
- 一个函数A的返回值是一个函数B, 那么这种操作被称为返回函数
def aFunc(symbol):
def add(num1, num2):
print(num1 + num2)
def subtract(num1, num2):
print(num1 - num2)
if symbol == "+":
return add
if symbol == "-":
return subtract
aFunc("+")(1, 2) # 打印: 3
aFunc("-")(5, 3) # 打印: 2
- 上述
aFunc
函数, 根据传入的参数不同, 返回不同的函数, 进行不同的操作
匿名函数
- 即没有名字的函数, 也称为 "lambda函数"
- 表达式:
lambda 参数列表: 表达式
- 限制
- 只能写一个表达式, 且不能return
- 表达式的结果就是返回值
- 只适用于一些简单的操作
- 示例:
func = lambda x, y : x + y
result = func(1, 2)
print(result) # 打印: 3
闭包
- 概念:
- 在嵌套函数的前提下
- 内层函数引用了外层函数的变量(包括参数)
- 外层函数, 又把内层函数 当做返回值进行返回
def test1():
a = 10
def test2():
print(a)
return test2
newFunc = test1()
newFunc() # 打印 10
- 一个简单的应用场景: 绘制分割线
def line_config(content, num): print("-" * (num // 2) + content + "-" * (num // 2)) print("呵呵", 20) # 打印: ----------呵呵----------
- 此时每次调用都需要使用代码
print("呵呵", 20) # 打印: ----------呵呵----------
- 如果每次的
content
和num
不同, 那么无可厚非, 但是如果每次调用时参数一致, 那么就显得比较麻烦, 此时就可以使用闭包形式对上面代码进行改动
def line_config(content, num): def line(): print("-" * (num // 2) + content + "-" * (num // 2)) return line newFunc = line_config("呵呵", 20) newFunc() # 打印: ----------呵呵---------- newFunc() # 打印: ----------呵呵---------- newFunc() # 打印: ----------呵呵---------- newFunc() # 打印: ----------呵呵----------
- 此时如果需要新的函数, 可以如下使用
newFunc2 = line_config("哈哈", 20) newFunc2() # 打印: ----------哈哈---------- newFunc2() # 打印: ----------哈哈---------- newFunc2() # 打印: ----------哈哈---------- newFunc2() # 打印: ----------哈哈----------
- 此时每次调用只需使用newFunc2函数
- 注意事项一: 闭包中内部函数修改外部函数中的变量(包括参数)
- 需要使用关键字
nonlocal
声明需要被修改的变量, 否则会默认为内部函数新定义的变量, 与外界变量无关
def test(): num = 10 def test2(): nonlocal num num = 666 print(num) test2() print(num) return test2 test()()
- 上诉代码中的打印结果为
10 666
- 如果注销掉
nonlocal num
, 那么最后打印的结果是
10 10
- 需要使用关键字
- 注意事项二: 函数, 是被调用时, 才去确定变量标识所对应的值
def test1(): funcs = [] for i in range(0, 3): def test2(): print(i) funcs.append(test2) return funcs arr = test1() print(arr) arr[0]() arr[1]() arr[2]()
- 打印结果如下:
[
.test2 at 0x1044227b8>, .test2 at 0x104422840>, .test2 at 0x1044228c8>] 2 2 2 列表中三个函数的地址不同, 说明是是三个不同的函数, 此时分别取出调用, 发现结构都是 2
这说明在执行
test1()
时, 内部的test2
函数没有被调用过只有在从列表中取出时才调用, 此时i的值已经循环到最大的2
此时才确定i的值, 所以打印都是2
如果想打印出0, 1, 2, 可以使用下面的代码
def test(): funcs = [] for i in range(0, 3): def test2(num): def test1(): print(num) return test1 funcs.append(test2(i)) return funcs newFuncs = test() print(newFuncs) newFuncs[0]() # 0 newFuncs[1]() # 1 newFuncs[2]() # 2