zoukankan      html  css  js  c++  java
  • Python 函数的一些用法

    高阶函数

    将函数 a 作为变量传给另一个函数 b,函数 b 就是一个高阶函数。

    def b(a):
        num = 2 - 5
        return a(num)
    a = abs
    result = b(a)
    print(result) # 3
    

    Python 内置的高阶函数中,有几个很常用。

    map() 函数。

    如果想要将一个可迭代对象中的元素全部按照某种规则修改,就可以用 map()
    map() 的用法为:map(func, iter)

    • func:是一个函数,表示规则
    • iter:是可迭代对象

    比如想要把列表 [1, 2, 3] 的元素全部乘 2,可以这样写:

    demo_list = [1, 2, 3]
    result = map(lambda x: x * 2, demo_list)
    print(list(result)) # [2, 4, 6]
    

    map() 返回迭代器,常与 lambda 配合使用。

    reduce() 函数

    reduce() 描述起来不太直观,直接看示例。
    reduce() 的用法为:reduce()

    • func:是一个接收两个参数的函数,表示规则
    • iter:是可迭代对象

    比如给出一个列表,想要求和:[1, 2, 3, 4]

    from functools import reduce
    
    demo_list = [1, 2, 3, 4]
    result = reduce(lambda x, y: x + y, demo_list)
    print(result) # 10
    

    在这个例子中,先把 12 分别作为 xy,其返回值和后一个元素 3 分别作为下一个 xy,按照这样递归的模式一直执行,直到迭代完成,返回结果。
    reduce 也可配合 lambda 使用。

    reduce() 结合 map() 可以写一个将字符串转为整型的算法。

    from functools import reduce
    STR_2_INT_MAP = {
        "0" : 0,
        "1" : 1,
        "2" : 2,
        "3" : 3,
        "4" : 4,
        "5" : 5,
        "6" : 6,
        "7" : 7,
        "8" : 8,
        "9" : 9,
    }
    demo_str = "12345"
    result = reduce(
        lambda a, b : a * 10 + b,
        map(
            lambda x : STR_2_INT_MAP[x],
            demo_str
        )
    )
    print(result) # 12345
    

    filter() 函数

    filter() 可以从可迭代对象中筛选出符合给定的规则的元素,返回生成器。
    写法:filter(func, iter)

    • func:是一个函数,表示规则
    • iter:可迭代对象

    比如筛选出 [1, 2, 3, 4, 5, 6, 7] 中的偶数:

    demo_list = [1, 2, 3, 4, 5, 6, 7]
    result = filter(
        lambda x: x % 2 == 0,
        demo_list
    )
    print(list(result)) # [2, 4, 6]
    

    sorted() 函数

    写法:sorted(iter, key, reverse)

    • iter:可迭代对象
    • key:是一个函数,排序的规则,这个参数是内置的
    • reverse:是否反转,这个参数是内置的

    比如要得到 [3, 6, 3, 8, 9, 6, 7, 1] 排序后的结果:

    demo_list = [3, 6, 3, 8, 9, 6, 7, 1]
    result = sorted(demo_list)
    print(result) # [1, 3, 3, 6, 6, 7, 8, 9]
    

    sorted()sort() 不同,
    sorted(demo_list) 返回一个新列表,内容是排序的结果,
    demo_list.sort() 是直接改变了 demo_list,且没有返回值。

    闭包

    闭包实质上就是函数里面再写个函数,然后把子函数作为返回值,子函数的数量无限制。

    一个常规的求和函数可以是这样:

    def get_sum(nums):
        result = 0
        for num in nums:
            result += num
        return result
    nums = [1, 2, 3, 4, 5]
    result = get_sum(nums)
    print(result) # 15
    

    将这个求和函数改成懒加载的形式:

    def get_sum(nums):
        def inner_sum():
            result = 0
            for num in nums:
                result += num
            return result
        return inner_sum
    nums = [1, 2, 3, 4, 5]
    func_result = get_sum(nums)
    print(func_result) # <function get_sum.<locals>.inner_sum at 0x7fc11311e940>
    print(func_result()) # 15
    

    闭包中的子函数引用的是变量,而不是变量的值。比如下面这个闭包:

    def square():
        result = []
        for num in [1, 2, 3]:
            def sq():
                return num * num
            result.append(sq)
        return result
    re1, re2, re3 = square()
    print(re1) # <function square.<locals>.sq at 0x7fc11272a700>
    print(re2) # <function square.<locals>.sq at 0x7fc11272aca0>
    print(re3) # <function square.<locals>.sq at 0x7fc11272a940>
    
    """
    这三个函数引用中,引用的是 num * num 这个变量,不是值
    当循环结束后,num 已经都变成了 3,所以全部返回 9。
    """
    print(re1()) # 9
    print(re2()) # 9
    print(re3()) # 9
    

    如果一定要引用值,就要再加一层子函数:

    def square():
        def sq(num):
            def sq_value():
                return num * num 
            return sq_value
        result = []
        for num in [1, 2, 3]:
            result.append(
                sq(num)
            )
        return result
    
    re1, re2, re3 = square()
    print(re1) # <function square.<locals>.sq.<locals>.sq_value at 0x7fc1127d5ca0>
    print(re2) # <function square.<locals>.sq.<locals>.sq_value at 0x7fc1127d5940>
    print(re3) # <function square.<locals>.sq.<locals>.sq_value at 0x7fc1127d5430>
    
    print(re1()) # 1
    print(re2()) # 4
    print(re3()) # 9
    

    装饰器

    装饰器可以在不改变函数逻辑的情况下,增加一些功能。比如给出一个求和函数:

    def get_sum():
        nums = [1, 2, 3, 4, 5]
        result = 0
        for num in nums:
            result += num
        return result
    result = get_sum()
    print(result) # 15
    

    现在如果要在运行这个函数的开始打印日志,就可以另写一个函数 dec_get_sum(),然后在 get_sum() 头上加 @dec_get_sum 实现装饰器的效果。

    def dec_get_sum(func):
        def wrapper(*args, **kwargs): # 形参写作 *args, **kwargs,表示接受任何参数
            print(
                f"开始求和...函数名称为:{func.__name__}" # func.__name__ 可以拿到函数的名称
            )
            return func(*args, **kwargs)
        return wrapper
    
    @dec_get_sum
    def get_sum():
        nums = [1, 2, 3, 4, 5]
        result = 0
        for num in nums:
            result += num
        return result
    result = get_sum()
    print(result)
    """
    开始求和...函数名称为:get_sum
    15
    """
    

    给函数加装饰器 @dec_get_sum 等效于执行:get_sum = dec_get_sum(get_sum)
    如果要自定义日志的内容,装饰器函数就需要在外面再套一层:

    import functools
    def print_log(text):
        def dec_get_sum(func):
            @functools.wraps(func)
            def wrapper(*args, **kwargs): # 形参写作 *args, **kwargs,表示接受任何参数
                print(
                    f"开始求和...当前时间为:{text},函数名称为:{func.__name__}" # func.__name__ 可以拿到函数的名称
                )
                return func(*args, **kwargs)
            return wrapper
        return dec_get_sum
    
    import time
    @print_log(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
    def get_sum():
        nums = [1, 2, 3, 4, 5]
        result = 0
        for num in nums:
            result += num
        return result
    result = get_sum()
    print(result)
    """
    开始求和...当前时间为:2021-09-07 11:44:21,函数名称为:get_sum
    15
    """
    
    print(get_sum.__name__) # 'wrapper'
    

    @print_log("text") 的实质是:get_sum = print_log("text")(get_sum)

    这时如果打印一下 get_sum__name__,发现函数名称已经被改变了,需要用一个内置的方法修正:functools.wraps(func)。修改后的代码如下:

    import functools
    def print_log(text):
        def dec_get_sum(func):
            @functools.wraps(func)
            def wrapper(*args, **kwargs): # 形参写作 *args, **kwargs,表示接受任何参数
                print(
                    f"开始求和...当前时间为:{text},函数名称为:{func.__name__}" # func.__name__ 可以拿到函数的名称
                )
                return func(*args, **kwargs)
            return wrapper
        return dec_get_sum
    
    import time
    @print_log(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
    def get_sum():
        nums = [1, 2, 3, 4, 5]
        result = 0
        for num in nums:
            result += num
        return result
    result = get_sum()
    print(result)
    """
    开始求和...当前时间为:2021-09-07 11:50:59,函数名称为:get_sum
    15
    """
    
    print(get_sum.__name__) # get_sum
    

    偏函数

    想要改变函数的某个参数的默认值,作为一个新函数,这时就可以用偏函数。

    比如对于内置的 int() 函数:
    int() 函数实质为:指定参数的进制,返回其 10 进制,可以用 base 指定当前参数的进制。

    print(int("123")) # 123,base 默认为10,0 也是十进制
    print(int("123", base=2)) # 报错,因为123不是二进制数
    print(int("010101", base=2)) # 21
    

    定义一个二进制转十进制的函数

    import functools
    bin_2_dec = functools.partial(int, base=2)
    print(bin_2_dec("010101")) # 21
    

    (本文完)

  • 相关阅读:
    Oracle 实现自动递增的功能
    解决升级chrome导致“Silverlight ”插件失效
    解决笔记:转载篇
    MSP432在CCS上新建工程,导入固件库
    操作系统复习文档
    数据结构
    数据结构
    蓝桥
    ACM山东工商 数据结构与算法 第3章 双向栈的操作
    ACM山东工商 栈和队列算法练习
  • 原文地址:https://www.cnblogs.com/junsircoding/p/15664976.html
Copyright © 2011-2022 走看看