zoukankan      html  css  js  c++  java
  • Python 函数式编程

    匿名函数lambda表达式 

    什么是匿名函数?

    匿名函数,顾名思义就是没有名字的函数,在程序中不用使用 def 进行定义,可以直接使用 lambda 关键字编写简单的代码逻辑。lambda 本质上是一个函数对象,可以将其赋值给另一个变量,再由该变量来调用函数,也可以直接使用。 

    #平时,我们是先定义函数,再进行调用
    def power(x):
        return x ** 2
    
    print(power(2))
    
    #使用lambda表达式的时候,我们可以这样操作
    power = lambda x : x ** 2
    print(power(2))
    
    #觉得太麻烦,还可以这样调用
    print((lambda x: 2 * x)(8))

    lambda表达式的基本格式:lambda 入参 : 表达式

    #入参可以有多个,比如 
    power = lambda x, n: x ** n
    
    print(power(2, 3))

    lambda 表达式的使用场景 

    一般适用于创建一些临时性的,小巧的函数。比如上面的 power函数,我们当然可以使用 def 来定义,但使用 lambda 来创建会显得很简洁,尤其是在高阶函数的使用中。 

    定义一个函数,传入一个list,将list每个元素的值加1

    def add(l = []):
        return [x +1 for x in l]
    
    print(add([1,2,3]))

    上面的函数改成将所有元素的值加

    可能大家会说,这还不简单,直接把return里的1改成2就行了。但是真的行吗?如果函数被多个地方使用,而其他地方并不想加2,怎么办? 

    这好办,把变得那部分抽出来,让调用者自己传

    def add(func,l = []):
        return [func(x) for x in l]
    
    def add1(x):
        return x+1
    
    def add2(x):
        return x+2
    
    print(add(add1,[1,2,3]))
    print(add(add2,[1,2,3]))    

    一个简简单单的问题,一定要用这么多代码实现?

    def add(func,l = []):
        return [func(x) for x in l]
    
    print(add(lambda x:x+1,[1,2,3]))
    print(add(lambda x:x+2,[1,2,3]))

    map函数

    map的基本格式 

    map(func, *iterables)

    map() 函数接收两个以上的参数,开头一个是函数,剩下的是序列,将传入的函数依次作用到序列的每个元素,并把结果作为新的序列返回。也就是类似 map(func,[1,2,3]) 

    同样的,我们还是来完成这样一个功能:将list每个元素的值加1

    def add(x):
        return x + 1
    
    result = map(add, [1, 2, 3, 4])
    print(type(result))
    print(list(result))

    使用lambda表达式简化操作

    result = map(lambda x: x + 1, [1, 2, 3, 4])
    print(type(result))
    print(list(result))

    函数中带两个参数的map函数格式 

    使用map函数,将两个序列的数据对应位置求和,之后返回,也就是对[1,2,3],[4,5,6]两个序列进行操作之后,返回结果[5,7,9] 

    print(list(map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])))

    对于两个序列元素个数一样的,相对好理解。如果两个序列个数不一样的,会不会报错?

    print(list(map(lambda x, y: x + y, [1, 2, 3], [4, 5])))

    我们可以看到不会报错,但是结果以个数少的为准

    reduce函数

    reduce函数的基本格式 

    reduce(function, sequence, initial=None)

    reduce把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce函数把结果继续和序列的下一个元素做累积计算,跟递归有点类似,reduce函数会被上一个计算结果应用到本次计算中 

    reduce(func, [1,2,3]) = func(func(1, 2), 3)

    使用reduce函数,计算一个列表的乘积

    from functools import reduce
    
    def func(x, y):
        return x * y
    
    print(reduce(func, [1, 2, 3, 4]))

    结合lambda表达式,简化操作

    from functools import reduce
    
    print(reduce(lambda x, y: x * y, [1, 2, 3, 4]))

    filter 函数

    filter 顾名思义是过滤的意思,带有杂质的(非需要的数据),经过 filter 处理之后,就被过滤掉。 

    filter函数的基本格式

    filter(function_or_None, iterable)

    filter() 接收一个函数和一个序列。把传入的函数依次作用于每个元素,然后根据返回值是 True 还是 False 决定保留还是丢弃该元素。 

    使用 filter 函数对给定序列进行操作,最后返回序列中所有偶数

    print(list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5])))

    sorted 函数

    sorted从字面上就可以看去这是个用来排序的函数,sorted 可以对所有可迭代的对象进行排序操作 

    sorted的基本格式 

    sorted(iterable, key=None, reverse=False)
    
    #iterable -- 可迭代对象。
    #key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
    #reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。 
    #对序列做升序排序
    print(sorted([1, 6, 4, 5, 9]))
    
    #对序列做降序排序
    print(sorted([1, 6, 4, 5, 9], reverse=True))
    
    #对存储多个列表的列表做排序
    data = [["Python", 99], ["c", 88]]
    print(sorted(data, key=lambda item: item[1]))

    闭包 

    在万物皆对象的Python,函数是否能作为函数的返回值进行返回呢? 

    def my_power():
        n = 2
        def power(x):
            return x ** n
        return power
    
    p = my_power()
    print(p(4))
    
    #------------------------------------------------------------
    def my_power():
        n = 2
        def power(x):
            return x ** n
        return power
    
    n = 3
    p = my_power()
    print(p(4))

    我们可以看到,my_power 函数在返回的时候,也将其引用的值(n)一同带回,的值被新的函数所使用,这种情况我们称之为闭包 

    当我们把n的值移除到my_power函数外面,这个时候来看下计算结果

    n = 2
    
    def my_power():
        def power(x):
            return x ** n
        return power
    
    n = 3
    p = my_power()
    print(p(4))

    为什么输出的结果会是64? 

    我们先来看看闭包时,p.__closure____的结果 

    #例1
    def my_power():
        n = 2
        def power(x):
            return x ** n
        return power
    
    p = my_power()
    print(p.__closure__)
    
    #结果:(<cell at 0x00000264518F9A38: int object at 0x00007FFA7F617120>)
    #closure是内部函数的一个属性,用来保存环境变量
    
    #---------------------------------------------------------------------
    
    #例2
    n = 2
    def my_power():
        def power(x):
            return x ** n
        return power
    
    n = 3
    p = my_power()
    print(p.__closure__)
    
    #输出结果 None

    通过例1跟例2对比,我们可以知道,例2并不是闭包

    闭包经典问题 

    下面的程序是否是闭包?能否正确运行 

    def my_power():
        n = 2
        
        def power(x):
            n += 1
            return x ** n
        
        return power
    
    p = my_power()
    print(p(3))

    如何让上面的程序正确运行?看看改正之后的结果

    def my_power():
        n = 2
        
        def power(x):
            nonlocal n
            n += 1
            return x ** n
        
        return power
    
    p = my_power()
    print(p.__closure__)
    print(p(3))
    print(p(3))

    看看下面的程序的运行结果

    def my_power():
        n = 2
        L = []
        for i in range(1, 3):
            def power():
                return i ** n
            
            L.append(power)
        return L
    
    f1, f2 = my_power()
    print(f1())
    print(f2())
    print(f1.__closure__[0].cell_contents)
    print(f2.__closure__[0].cell_contents)

    python的函数只有在执行时,才会去找函数体里的变量的值,也就是说你连形参都不确定,你咋求知道 i为几呢?在这里,你只需要记住如果你连形参都不确定,python就只会记住最后一个i值。 

     

    装饰器及其应用

    什么是装饰器模式

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

    这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。 

    import time
    
    start = time.time()
    time.sleep(4)
    end = time.time()
    print(end - start)

    从实际例子来看装饰器

    def my_fun():
        print("这是一个函数")
    
    my_fun()

    要再打印这是一个函数前面在打印多一行hello world

    def my_fun():
        begin = time.time()
        time.sleep(2)
        print("这里一个函数")
        end = time.time()
        print(end-begin)
    
    my_fun()

    这个时候,如果不想修改原有的函数,咋整?

    def my_fun():
        print("这是一个函数")
    
    def my_time(func):
        begin = time.time()
        time.sleep(2)
        func()
        end = time.time()
        print(end - begin)
    
    my_time(func)

    这种方式,因为要增加功能,导致所有的业务调用方都得进行修改,此法明显不可取。 

    另一种方式: 

    def print_cost(func):
        def wrapper():
            begin = time.time()
            time.sleep(2)
            func()
            end = time.time()
            print(end - begin)
            return wrapper
    
    @print_cost
    def my_fun():
        print("这里一个函数")

    第二种方式并没有修改func函数的内部实现,而是使用装饰器模式对其功能进行装饰增强。

  • 相关阅读:
    32、至少列举8个常用模块都有那些?
    31、如何安装第三方模块?以及用过哪些第三方模块?
    uva120 Stacks of Flapjacks (构造法)
    stringstream的基本用法
    Codeforces Round #246 (Div. 2) C. Prime Swaps(贪心,数论)
    Codeforces Round #271 (Div. 2)D(递推,前缀和)
    poj3061 Subsequence&&poj3320 Jessica's Reading Problem(尺取法)
    Codeforces Round #266 (Div. 2)B(暴力枚举)
    uva10815(set的应用)
    uva489(需要考虑周全)
  • 原文地址:https://www.cnblogs.com/jwen1994/p/13127205.html
Copyright © 2011-2022 走看看