[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操作都可以被生成器或其他内置函数所代替,当作为参数来使用的使用的时候,应尽量考虑有没有其他的可替代写法或者更有效的内置方法。

posted @ 2020-07-01 09:34  wildkid1024  阅读(160)  评论(0编辑  收藏  举报