• python学习第十一天 -- 函数式编程


    在介绍函数式编程之前,先介绍几个概念性的东西。

    什么是函数式编程?

    函数式编程的特点:

    1.把计算视为函数而非指令;

    2.纯函数式编程:不需要变量,没有副作用,测试简单;

    3.支持高阶函数,代码简洁。

    什么是高阶函数?

    能接收函数做参数的函数,称为高阶函数。

    高阶函数的特点:

    1.变量可以指向函数

    2.函数的参数可以接收变量

    3.一个函数可以接收另一个函数作为参数

    Python支持的函数式编程?

    1.不是纯函数式编程:允许有变量

    2.支持高阶函数:函数也可以作为变量传入

    3.支持闭包:有了闭包就能返回函数

    4.有限度的支持匿名函数

    关于匿名函数和闭包的介绍,后面会一一介绍,暂时不在这里详细介绍。

    高阶函数-把函数作为参数

    >>> def fn(x,y,f):
    ...     return f(x)+f(y)
    ...
    >>> import math
    >>> fn(4,16,math.sqrt)
    6.0

    python内置的几个常用的高阶函数

    map():接收一个函数f和一个list对象,函数f作用于list对象的每一个元素,并返回一个新的list对象。

    >>> def fn(x):
    ...     return x*x;
    ...
    >>> print map(fn,range(1,11))
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    reduce():也是接收函数f和一个list对象,但是接收函数f必须传入两个参数,然后对lsit中的每一个元素反复调用函数f,并返回最终结果值。

    >>> def prod(x,y):
    ...     return x*y
    ...
    >>> print reduce(prod,range(1,6))
    120 //1 *2*3*4*5

    filter():接收函数f和一个list对象,函数f的作用是对每一个list对象的元素进行判断,返回true 和false。filter()根据判断结果自动过滤掉不符合的元素,返回符合条件的元素组成的新list。

    >>> def is_even_number(x):
    ...     return x%2==0
    ...
    >>> filter(is_even_number,range(1,11))
    [2, 4, 6, 8, 10]

    上面针对高阶函数讲解,大家应该了解了函数是可以作为参数的,那么既然函数可以做参数,那么也可以返回函数。

    返回函数

    >>> def f():
    ...     print 'call f()....'
    ...     //定义函数g:
    ...     def g():
    ...          print 'call g()....'
            //返回函数g:
    ...     return g
    ...
    >>> x = f() //调用f()
    call f()....
    >>> x 
    <function g at 0x7f62fab01c80>
    >>> x() //调用x()就是执行g()函数定义的代码
    call g()....

    举个例子:编写一个函数,接收一个list,返回一个函数,返回函数可以计算参数的乘积。

    >>> def fn(x,y):
    ...     return x*y;
    ...
    >>> def calc_prod(lst):
    ...     def my_calc():
    ...         return reduce(fn,lst)
    ...     return my_calc
    ...
    >>> f = calc_prod(range(1,5))
    >>> print f()
    24

    闭包

    内层函数引用外层函数的变量,然后返回内层函数的情况,称为闭包。

    闭包的特点:返回的函数引用了外层函数的局部变量。所以,要正确使用闭包,就能确保引用的局部变量在函数返回后不能改变。举例说明:

    //希望一次返回3个函数,分别计算1x1,2x2,3x3
    >>> def count():
    ...     lst = []
    ...     for i in range(1,4):
    ...         def f():
    ...              return i*i
    ...         lst.append(f)
    ...     return lst
    ...
    >>> f1,f2,f3 = count()
    >>> f1()
    9
    >>> f2()
    9
    >>> f3()
    9

    得到的结果并不是我们预期的1,4,9.

    lst.append(f),只是将每一个f()的引用保存进了list,并没有进行对于i的计算,所以导致最后在运行了f(1)之后,i已经变为了3.

    因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量

    那么怎么改写上述的代码,得到想要的1,4,9.值。

    方法一:

    >>> def count():
    ...     lst = []
    ...     for i in range(1,4):
    ...          def f():
    ...               return i*i
    ...          lst.append(f()) //很大的不同,f 变为了f(),这一步的时候已经进行了i*i的运算
    ...     return lst
    ...
    >>> f1,f2,f3 = count()
    >>> print f1,f2,f3
    1 4 9

    方法二:

    >>> def count():
    ...     lst = []
    ...     for i in range(1,4):
    ...          def f(m=i)://传入参数
    ...               return m*m
    ...          lst.append(f) 
    ...     return lst
    ...
    >>> f1,f2,f3 = count()
    >>> print f1(),f2(),f3()
    1 4 9

    问题的产生是因为函数只在执行时才去获取外层参数i,若函数定义时可以获取到i,问题便可解决。而默认参数正好可以完成定义时获取i值且运行函数时无需参数输入的功能,所以在函数f()定义中改为f(m = i),函数f返回值改为m*m即可.

    匿名函数

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

    匿名函数有个限制,就是只能有一个表达式,不能写return,返回值就直接写表达式的结果。

    例子一:

    >>> map(lambda x:x*x,range(1,5))
    [1, 4, 9, 16]

    lambda x:x*x,可以看做是

    >>> def f(x):
    ...     return x*x

    例子二:

    >>> myabs = lambda x:-x if x<0 else x
    >>> myabs(-1)
    1
    >>> myabs(2)
    2

    lambda x:-x if x<0 else x可以看做是

    >>> def f(x):
    ...     x = -x
    ...     if x<0:
    ...         return -x
    ...     else:
    ...         return x

    小结:这一节主要讲解python函数式编程概念及其python高阶函数的定义及其使用。

  • 相关阅读:
    Python-环境配置
    Linux操作系统基
    BZOJ 1572 贪心(priority_queue)
    POJ 3040 贪心
    POJ 3039 搜索??? (逼近)
    POJ 2433 枚举
    BZOJ 1571 DP
    BZOJ 1232 Kruskal
    BZOJ 1231 状压DP
    POJ 2430 状压DP
  • 原文地址:https://www.cnblogs.com/nx520zj/p/5725431.html
Copyright © 2020-2023  润新知