美文网首页
装饰器与偏函数

装饰器与偏函数

作者: 5f2a6061653d | 来源:发表于2019-03-04 09:37 被阅读20次

装饰器的概念

在讲解装饰器之前,先看一段简单的程序,如下所示。

 1  def f2(func):
 2      def f1():
 3          x = func()
 4          return x + 1
 5      return f1
 6  def func():
 7      print('func()函数')
 8      return 1
 9  decorated = f2(func)
 10 print(decorated())
 11 print(func())

运行结果如下图所示。

运行结果
在上例中, 第1行定义了一个带单个参数func的名称为 f2的函数,第2行f1()函数为闭包,其中调用了func()函数并将func()函数的返回值加1返回。这样每次f2()函数被调用时,func的值可能会不同,但不论func()代表何种函数,程序都将调用它。
从程序运行结果可看出,调用函数decorated()的返回值为2,调用func()函数的返回值为1,两者都输出“func()函数”,此时称变量decorated是func的装饰版,即在func()函数的基础上增加新功能,上例是将func()函数的返回值加1。
大家可以用装饰版来代替func,这样每次调用时就总能得到附带其他功能的 func 版本,如下所示。
 1  def f2(func):
 2      def f1():
 3          return func() + 1
 4      return f1
 5  def func():
 6      print('func()函数')
 7      return 1
 8  func = f2(func)
 9  print(func())

运行结果如下图所示。


运行结果

在上述代码中,第3行等价于上例中第3、4行,第8行将上例中第9行decorated改为func,这样每次通过函数名func调用函数时,都将执行装饰的版本。
通过上述代码可以得出装饰器的概念,即一个以函数作为参数并返回一个替换函数的可执行函数。装饰器的本质是一个嵌套函数,外层函数的参数是被修饰的函数,内层函数是一个闭包并在其中增加新功能。

@符号的应用

上例中使用变量名将装饰器函数与被装饰函数联系起来,此外,还可以通过@符号和装饰器名实现两者的联系,如下所示。

 1  def f2(func):
 2      def f1():
 3          return func() + 1
 4      return f1
 5  @f2
 6  def func():
 7      print('func()函数')
 8      return 1
 9  print(func())

运行结果如下图所示。


运行结果

在上例中,第5行通过@符号和装饰器名实现装饰器函数与被装饰函数联系,第9行调用func()函数时,程序会自动调用装饰器函数的代码。

装饰有参数的函数

装饰器除了可以装饰无参数的函数外,还可以装饰有参数的函数,如下所示。

 1  def f2(func):
 2      def f1(a = 0, b = 0):
 3          return func(a, b) + 1
 4      return f1
 5  @f2
 6  def func(a = 0, b = 0):
 7      print('func()函数')
 8      return a + b
 9  print(func(6, 8))

运行结果如下图所示。


运行结果

在上例中,第6行定义一个带有两个默认参数的func()函数,第5行将f2()函数声明为装饰器函数,用来修饰func()函数,第9行调用func装饰器函数,注意f1()函数中的参数必须包含对应func()函数的参数。

带参数的装饰器

通过上面的学习,装饰器本身也是一个函数,即装饰器本身也可以带参数,此时装饰器需要再多一层内嵌函数,如下所示。

 1  def f3(arg = '装饰器的参数'):
 2      def f2(func):
 3          def f1():
 4              print(arg)
 5              return func() + 1
 6          return f1
 7      return f2
 8  @f3('带参数的装饰器')
 9  def func():
 10     print('func()函数')
 11     return 1
 12 print(func())

运行结果如下图所示。


运行结果

在上例中,第1行定义装饰器函数,其由三个函数嵌套而成,最外层函数有一个装饰器自带的参数,内层函数不变,相当于闭包的嵌套。第8行将f3()函数声明为装饰器函数,用来修饰func()函数。
若读者不理解此代码,可以将装饰器写成如下代码,如下所示。

 1  def f3(arg = '装饰器的参数'):
 2      def f2(func):
 3          def f1():
 4              print(arg)
 5              return func() + 1
 6          return f1
 7      return f2
 8  def func():
 9      print('func()函数')
 10     return 1
 11 f2 = f3('带参数的装饰器')
 12 func = f2(func)
 13 print(func())

运行结果如下图所示。


运行结果

在上例中,将装饰器分解成闭包的嵌套,这种写法更容易理解,此外,还可以将第11、12行代码写成如下代码:

func = f3('带参数的装饰器')(func)

上述代码相当于省略中间变量f2。

偏函数

函数最重要的一个功能的是复用代码,有时在复用已有函数时,可能需要固定其中的部分参数,除了可以通过默认值参数来实现之外,还可以使用偏函数,如下所示。

 1  def myAdd1(a, b, c):
 2      return a + b + c
 3  def myAdd2(a, b):
 4      return myAdd1(a, b, 123)
 5  print(myAdd2(1, 1))

运行结果如下图所示。


运行结果

在上例中,第3行定义一个myAdd2()函数,与第1行myAdd1()函数的区别仅在于参数c固定为一个数字123,这时就可以使用偏函数的技术来复用上面的函数。

相关文章

  • 笨笨的学pythonDay06

    接着昨天未学完的函数,还有个偏函数和装饰器,先说一下偏函数,装饰器没有看明白 1.偏函数 偏函数可以通过将函数参数...

  • Python:6.函数式编程

    返回函数 匿名函数 装饰器 偏函数

  • Python 返回函数、匿名函数、装饰器、偏函数

    返回函数 匿名函数 装饰器 偏函数

  • 装饰器与偏函数

    装饰器的概念 在讲解装饰器之前,先看一段简单的程序,如下所示。 运行结果如下图所示。 运行结果如下图所示。 在上述...

  • chapter7 函数式编程

    闭包 匿名函数 装饰器 偏函数

  • Python ☞ day 5

    Python学习笔记之 装饰器& 偏函数 & 异常处理 & 断言 & 文件读写 &编码与解码 装饰器 概念:是一个...

  • py装饰器与偏函数

    一、装饰器 1、将函数赋值给对象 函数对象有一个name属性,可以拿到函数的名字 2、装饰器decorator 在...

  • Python基础-day08

    list ​ 可变参数 ​ 关键字参数 ​ 匿名函数 ​ 闭包 ​ 偏导函数 ​ 装饰器 ...

  • Python干货-装饰器与偏函数

    装饰器 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返...

  • python四装饰器与偏函数

    装饰器 定义: 假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数...

网友评论

      本文标题:装饰器与偏函数

      本文链接:https://www.haomeiwen.com/subject/xfdcrqtx.html