zoukankan      html  css  js  c++  java
  • Python基础笔记:函数式编程:高阶函数、返回函数、匿名函数

    高阶函数

    高阶函数:一个函数可以接收另一个函数作为参数 或 一个函数可以返回一个函数作为返回值,这种函数称之为高阶函数。

    #函数 add 接收 f 函数作为参数
    >>> def add(x,y,f):
    ...     return f(x)+f(y)
    ...
    >>> add(-5,6,abs)
    11

    可以把匿名函数作为返回值返回

    #把匿名函数作为返回值返回
    def build(x, y):
        return lambda: x * x + y * y

    匿名函数

    关键字 lambda 表示匿名函数,冒号前面的 x 表示函数参数

    >>> list(map(lambda x:x*x,list(range(1,10))))
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    def f(x):
        return x*x
    >>> from hello import f
    >>> list(map(lambda x:x*x,list(range(1,10))))
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    #这两种方式等价,不过第一种代码量更少。
    def f(x):
        return x*x
    
    #等价于
    
    lambda x:x*x

    返回函数

    比如我们实现一个求和函数:

    def calc_sum(*args):
        ans=0
        for i in args:
            ans+=i
        return ans

    但是如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?

    可以不返回求和的结果,而是返回求和的函数:

    def lazy_sum(*args):
        def sum():
            ans=0
            for i in args:
                ans+=i
            return ans
        return sum
    #调用
    >>> L=list(range(1,11)) 
    >>> f=lazy_sum(*L) #返回的函数并没有立刻执行,而是直到调用了f
    >>> f()
    55

    在这个例子中,我们在函数 lazy_sum 中又定义了函数 sum ,并且,内部函数 sum可以引用外部函数 lazy_sum 的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

    当我们调用 lazy_sum() 时,每次调用都会返回一个新的函数,即使传入相同的参数:

    >>> f1=lazy_sum(*L)
    >>> f2=lazy_sum(*L)
    >>> f1==f2
    False

    一个关于“闭包”的示例:

    def count():
        fs=[]
        for i in range(1,4): #每次循环都创建了一个新的函数,然后把创建的3个函数都返回了
            def f():
                return i*i
            fs.append(f)
        return fs
    #调用
    >>> f1,f2,f3=count() 
    >>> f1()
    9
    >>> f2()
    9
    >>> f3()
    9

    怎么都是9 ?!

    原因在于返回的函数引用了变量 i ,但它并非立刻执行。等到三个函数都返回时,它们所引用的变量 i 已经变成了 3,因此最终结果为9......

    如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

    def count():
        fs=[]
        for i in range(1,4):
            def f(i):
                def g():
                    return i*i
                return g
            fs.append(f(i))
        return fs
    #调用
    >>> from hello import count
    >>> f1,f2,f3=count()
    >>> f1()
    1
    >>> f2()
    4
    >>> f3()
    9

    利用 lambda 函数简化:

    def count():
        fs=[]
        for i in range(1,4):
            def f(i):
                return lambda :i*i
            fs.append(f(i))
        return fs

    练习:利用闭包返回一个计数器函数,每次调用它返回递增整数

    def count_num():
        f=[0]
        def count():
            f[0]=f[0]+1
            return f[0]
        return count
    >>> from hello import count_num
    >>> f=count_num()
    >>> f()
    1
    >>> f()
    2
    >>> f()
    3
    >>>

    高阶函数——map

    map() 函数接收两个参数,一个是函数,一个是Iterable , map将闯入的函数一次作用到序列的每个元素,并把结果作为新的 Iterator 返回

    用 map 实现把一个函数 f(x)=x*x ,作用在一个 list 上后的结果输出:

    >>> L=range(1,11)
    >>> L=list(range(1,11))
    >>> r=map(lambda x:x*x,L)
    >>> list(r)
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    高阶函数——reduce

    reduce() 函数是接受两个参数,把一个函数最用在一个序列上,reduce 把结果继续和序列的下一个元素做累积计算,其效果就是:

    reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

    用reduce 实现序列求和

    >>> from functools import reduce #使用reduce函数需先import
    >>> L=list(range(1,11))
    >>> reduce(lambda x,y:x+y,L)
    55

    用reduce 实现把一个整数序列变成整数

    >>> L=list(range(1,10))
    >>> reduce(lambda x,y:x*10+y,L)
    123456789

    用reduce + map 实现str 转换为 int 的函数

    >>> def char_num(c):
    ...     digits={'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
    ...     return digits[c]
    ...
    >>> reduce(lambda x,y :x*10+y,list(map(char_num,'13654')))
    13654

    python 有内置的str 与int 互化的函数

    >>> str(4515)
    '4515'
    >>> int('5252')
    5252

    练习:利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']

  • 相关阅读:
    简单分析实现运维利器---web远程ssh终端录像回放libl
    利用kite对视频流应用进行压力测试
    Springboot 启动扩展
    SpringBoot 自动配置原理
    idea springboot没有启动项,或启动时找不到或无法加载主类
    Elasticsearch、Kibana、elasticsearch-analysis-ik 版本下载地址
    Springboot 操作Elasticsearch 方式二 【rest-high-level-client】
    Elasticsearch 安装x-pack之后,无法连接head问题
    ES版本是向下兼容的,springboot连接ES,可以用低版本客户端
    ES安装elasticsearch-head-master插件
  • 原文地址:https://www.cnblogs.com/jiaxinwei/p/8325598.html
Copyright © 2011-2022 走看看