当前位置:   article > 正文

python高阶函数闭包装饰器_Python函数:Lambda,闭包,装饰器和Currying

python高阶函数闭包装饰器_Python函数:Lambda,闭包,装饰器和Currying

了解Python中的四个高级函数概念

30ee8a2216294fef8f60a72a272963bc

> Photo by Tim Swaan on Unsplash.

Python函数是一段代码,可在需要运行时执行特定的操作,我们称其为函数。 大多数时候,我们使用以下语法声明并调用函数:

在上面的代码中,我们使用def关键字声明了一个名为add_up的函数。 此函数将两个数字(num1和num2)作为输入参数,计算它们的总和作为已定义的运算,然后将此值作为函数的输出返回。 很简单吧?

除了这些常规函数外,Python中还有其他种类的函数可以使我们的开发受益。 让我们在本文中对其进行回顾。

Lambda函数

Lambda函数是小的匿名单行函数。 有时,我们可以简单地将它们称为lambda。 Lambda具有以下语法:

lambda arguments: expression

我们使用lambda关键字声明一个lambda函数。 在此关键字之后,我们指定参数列表,其数量可以从零到多个变化。 然后,我们指定要执行的操作,称为lambda函数的表达式。

如您所见,lambda具有非常简洁的语法,因此它们最适合需要简短的一次性使用功能的场景。 让我们考虑以下示例。 sorted()函数用于根据key参数指定的key函数对可迭代对象进行排序:

>>> # define a list of tuples

>>> records = [(1, 'John'), (2, 'Aaron'), (5, 'Ian')]

>>> # sort with a lambda

>>> sorted(records, key=lambda x: len(x[1]))[(5, 'Ian'), (1, 'John'), (2, 'Aaron')]

在上面的代码中,我们首先定义一个列表来存储一些学生及其学生ID和姓名的记录。 然后,我们使用lambda函数对它们进行排序,该函数按学生姓名的长度对列表进行排序。

有关使用lambda函数进行排序的信息,请参阅我的上一篇文章。 同样重要的是要知道可能会滥用lambda。 为了方便起见,提供了以下文章:

闭包

闭包是嵌套函数,可捕获外部函数的非局部变量。 我认为从概念上理解闭包并不容易。 透彻的理解需要深入了解范围和函数(它们是Python中的一流对象)。 出于本文的目的,让我们通过看一个具体的示例来总体了解闭包:

>>> # create a closure

>>> def make_multiplier(coefficient):

... product = 1

...

... def multiplier():

... nonlocal product

... product *= coefficient

... return product

...

... return multiplier

...

在上面的代码中,我们定义了一个名为make_multiplier的函数。 因为它包含另一个函数乘法器,所以我们可以将make_multiplier称为外部函数,并将multiplier称为嵌套函数。 外部函数返回嵌套函数作为其返回值。 重要的是,嵌套函数使用并修改在外部函数范围内定义的非局部变量(即乘积)。 综上所述,在Python中创建闭包包含三个关键要素:

· 在外部函数的范围内声明一个嵌套函数。

· 嵌套函数范围之外的非局部变量的绑定。

· 返回嵌套函数以输出闭包函数。

我们如何使用闭包? 让我们看下面的简单例子:

>>> multipler3 = make_multiplier(3)

>>> multipler3()

3

>>> multipler3()

9

>>> multipler3()

27

>>> multipler3.__code__.co_freevars

('coefficient', 'product')

>>> multipler3.__closure__[1].cell_contents

27

然后,我们声明一个名为multiplier3的闭包。 每次我们称此闭包为乘积乘以3。 换句话说,封盖"记住"产品最后一次使用后的状态。 相关概念包括变量绑定和值捕获。 我们可以通过调用__code __。co_freevars和__closure __ [1] .cell_contents来检查相关信息。

装饰器

装饰器是可扩展其他功能的行为而无需显式修改它们的功能。 本质上,装饰器是一种高阶函数,定义为将其他函数作为输入或将其他函数作为输出返回的函数。 通过下面的示例,让我们真正了解装饰者:

>>> def clap():

... print("Clap! Clap!")

...

>>> # define a higher order function

>>> def triple_repeat_wrapper(func):

... def wrapper():

... print(f"Before calling func {func.__name__}")

... func()

... func()

... func()

... print(f"After calling func {func.__name__}")

... return wrapper

...

在上面的代码中,我们定义了两个函数(clap和Triple_repeat_wrapper),后者是一个高阶函数,该函数在嵌套包装函数中调用传递的func三次,然后将包装函数作为高阶函数的输出返回。

我们如何使用这些功能? 如下代码所示,我们创建了一个称为wrapd_clap的函数,该函数将拍手函数传递给高阶函数Triple_repeat_wrapper。 如您所见,调用wrapped_clap函数将导致嵌套包装器函数内部的代码被调用。 与打印输出一致,我们知道wrapped_clap函数引用了嵌套函数包装器。

>>> wrapped_clap = triple_repeat_wrapper(clap)

>>> wrapped_clap()

Before calling func clap

Clap! Clap!

Clap! Clap!

Clap! Clap!

After calling func clap

>>> wrapped_clap

.wrapper at 0x1038f0680>

但是,回想一下,当您看到一些有关装饰器的示例代码时,您肯定已经看到了@符号的用法。 这个符号如何与我们上面定义的功能一起发挥作用? 让我们通过参考以下代码来解决这个问题:

>>> @triple_repeat_wrapper

... def hooray():

... print("Hooray! Hooray!")

...

>>> hooray()

Before calling func hooray

Hooray! Hooray!

Hooray! Hooray!

Hooray! Hooray!

After calling func hooray

>>> hooray

.wrapper at 0x1038f0830>

在上面的代码中,我们声明了一个名为hooray的函数。 当我们调用此函数时,输出的格式与前一个wrapd_clap函数的输出相同。 同样,hooray函数引用嵌套包装器函数。

为什么会这样? 您可能已经注意到,在此hooray函数的声明上方,我们在Triple_repeat_wrapper函数名称之前使用@符号。 这只是装饰者的语法糖。 本质上,我们告诉Python解释器,我们将要定义的函数将由decorator函数包装。

Curry

以数学家Haskell Curry的名字命名的currying是指通过应用部分参数从现有函数创建新函数。 因此,该概念有时也称为部分功能。

与上述概念相比,这一概念更容易理解。 让我们考虑下面的简化示例,使用与上面定义的相同的add_up函数:

>>> # define a function returns a value

>>> def add_up(num1, num2):

... sum_n = num1+num2

... return sum_n

...

>>> # define a partial function that adds seven

>>> add_seven = lambda x: add_up(7, x)

>>> add_seven(10)

17

>>> add_seven(72)

79

>>> # use a regular def keyword

>>> def add_eight(x):

... return add_up(8, x)

...

>>> add_eight(10)

18

在上面的代码中,我们使用lambda函数将数字7设置为add_up函数的第一个参数。 换句话说,创建的add_seven函数是原始add_up的部分函数,第一个参数始终设置为7。除了使用lambda函数之外,使用常规方法通过def关键字定义函数当然是可以接受的。

functools模块中提供了另一个方便的用于创建部分功能的工具。 考虑以下示例。 我们使用partial函数创建add_ten函数,该函数的默认参数为10,该函数调用add_up函数:

总结

在本文中,我们回顾了Python函数基础之外的四个高级概念。 以下是这些概念的简要概述:

· Lambda是匿名函数,在需要简单的一次性内联函数的情况下非常方便。

· 闭包是嵌套函数,它们绑定周围范围的非局部变量。

· 装饰器是可修改其他功能的行为的高阶功能。

· Currying是我们通过设置一些默认参数从现有函数中创建部分函数的方法。

(本文翻译自Yong Cui, Ph.D.的文章《Python Functions: Lambdas, Closures, Decorators, and Currying》,参考:

https://medium.com/better-programming/python-functions-lambdas-closures-decorators-and-currying-83165d099abe)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/894391
推荐阅读
相关标签
  

闽ICP备14008679号