zoukankan      html  css  js  c++  java
  • [python]python进阶编程(2)-匿名函数和闭包

    说明

    python的一大特性是,其具备函数式编程语言的特性,这意味着function在python的世界中也是作为一等公民而存在的,今天就来讨论匿名函数和闭包。

    lambda函数

    lambda函数也称为匿名函数,多使用于只有一行逻辑的函数,可以使得代码简短易读。一个使用的场景如下所示:

    将列表 ['abc', 'def', 'g']按照首字母排序,如果是按照sorted的方法,那么对应的排序函数应该设置为:

    def get_first(s):
        return s[0]
    

    但是这一行的代码较为简单,且只使用一次,所以可以使用lambda来代替:

    l = ['hbc', 'kef', 'g']
    sorted_l = sorted(l, key= lambda s:s[0])
    print(sorted_l)
    

    lambda本身是一个匿名函数,一般只有一行,可以代替那些简单的函数。其格式为lambda param: return.其中param为对应参数,return为返回值。

    lambda函数赋值

    因为lambda函数是匿名的,所以可以通过赋值的方式进行传递,但是一般不推荐这么做,因为即便是匿名函数被赋值后,其本质上还是匿名函数,如果要使用带有名称的函数,还是使用def来定义。

     foo = lambda x, y: x + y
     print(foo) # <function test_lambda_type.<locals>.<lambda> at 0x0000021D000FEEE0>
    

    可以看出,即便是赋值,相应的函数仍然是lambda,这可能在某些场景下造成困惑。
    另外一个场景是通过lambda来禁用内置函数,如以下所示:

    time.sleep = lambda x: None
    

    上述函数禁用了sleep函数,但这样做是违背python的原则,不应当直接去覆盖内置函数,这样在使用的时候容易造成混乱,而一般的禁用方式则为继承+方法覆盖。

    lambda函数作为返回值传递

    因为函数在python里也是一等公民,所以可以返回值方式进行传递。

    def foo():
        return lambda x, y : x + y
    

    上述的代码中foo函数返回的是一个具有加法逻辑的匿名函数,这实际上是python闭包的概念。我们稍微讲解一下,以下就是一个普通的闭包:

    def foo():
        def bar():
            # do something
            return 
        return bar
    

    其中闭包中的bar函数可以使用foo函数中的参数,那么bar也可以根据foo的参数变换功能,具体来讲,就是需要根据参数来变换函数的场景。同样地,也可以对lambda函数进行嵌套来实现闭包:

    lambda x: lambda y : x + y
    

    不过这样一定程度上会使得可读性变差。

    lambda函数作为参数使用

    在map/filter/reduce的内置函数中,是接受lambda函数作为参数来使用的,但是通常情况下这些内置函数可以通过其他方式来代替,比如以下几种情况:

    • map:
    data = [1,2,3,4,5]
    result = map(lambda v:v**2, data)
    result = (v**2 for v in data) # 与map+lambda方法等效
    
    • filter
    data = [1,2,3,4,5]
    result = filter(lambda v:v>3, data)
    result = (v for v in data if v > 3) # 与filter+lambda方法等效
    
    • reduce
    data = [1,2,3,4,5]
    result = reduce(lambda x, y : x + y, data)
    result = sum(data) # 与reduce+lambda方法等效
    

    从上述的情况可以看出,大部分的map/filter/reduce操作都可以被生成器或其他内置函数所代替,当作为参数来使用的使用的时候,应尽量考虑有没有其他的可替代写法或者更有效的内置方法。

  • 相关阅读:
    12/21
    和寶寶在一起3/10
    11/23
    c#windows应用程序窗体间传值
    用OWC做统计图
    javascript 创建字典
    .NetCom双向数据交换的实现(RecordSet与.Net DataSet的转化)
    JScript 方法 indexOf 方法
    详尽解析window.event对象
    Window.Open详解
  • 原文地址:https://www.cnblogs.com/wildkid1024/p/13213974.html
Copyright © 2011-2022 走看看