Python基础(十一): 函数的几种使用方式

偏函数, 高阶函数, 返回函数, 匿名函数, 闭包

偏函数

  • 当我们写一个参数比较多的函数时, 如果有些参数, 大部分场景下都是某一个固定值, 那么为了简化使用, 就可以创建一个新函数, 指定我们要使用的函数的某个参数为某个固定的值; 这个新函数就是"偏函数"

  • 即: 在原有函数的基础上, 写一个新函数, 来简化这个函数的使用

  • 例如: 此时有一个函数, 拥有四个参数

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)       # 打印: ----------呵呵----------
    
    • 如果每次的contentnum不同, 那么无可厚非, 但是如果每次调用时参数一致, 那么就显得比较麻烦, 此时就可以使用闭包形式对上面代码进行改动
    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
    

你可能感兴趣的:(Python基础(十一): 函数的几种使用方式)