Python中用Decorator来简化元编程的教程

 更新时间:2015年04月13日 15:04:51   投稿:goldensun  
这篇文章主要介绍了Python中用Decorator来简化元编程的教程,来自于IBM官方开发者技术文档,需要的朋友可以参考下

少劳多得

Decorator 与 Python 之前引入的元编程抽象有着某些共同之处:即使没有这些技术,您也一样可以实现它们所提供的功能。正如 Michele Simionato 和我在 可爱的 Python 专栏的早期文章 中指出的那样,即使在 Python 1.5 中,也可以实现 Python 类的创建,而不需要使用 “元类” 挂钩。

Decorator 根本上的平庸与之非常类似。Decorator 所实现的功能就是修改紧接 Decorator 之后定义的函数和方法。这总是可能的,但这种功能主要是由 Python 2.2 中引入的 classmethod() 和 staticmethod() 内置函数驱动的。在旧式风格中,您可以调用 classmethod(),如下所示:
清单 1. 典型的 “旧式” classmethod

class C:
  def foo(cls, y):
    print "classmethod", cls, y
  foo = classmethod(foo)

虽然 classmethod() 是内置函数,但并无独特之处;您也可以使用自己的方法转换函数。例如:
清单 2. 典型的 “旧式” 方法的转换

def enhanced(meth):
  def new(self, y):
    print "I am enhanced"
    return meth(self, y)
  return new
class C:
  def bar(self, x):
    print "some method says:", x
  bar = enhanced(bar)

decorator 所做的一切就是使您避免重复使用方法名,并且将 decorator 放在方法定义中第一处提及其名称的地方。例如:
清单 3. 典型的 “旧式” classmethod

class C:
  @classmethod
  def foo(cls, y):
    print "classmethod", cls, y
  @enhanced
  def bar(self, x):
    print "some method says:", x

decorator 也可以用于正则函数,采用的是与类中的方法相同的方式。令人惊奇的是,这一切是如此简单(严格来说,甚至有些不必要),只需要对语法进行简单修改,所有东西就可以工作得更好,并且使得程序的论证更加轻松。通过在方法定义的函数之前列出多个 decorator,即可将 decorator 链接在一起;良好的判断可以有助于防止将过多 decorator 链接在一起,不过有时候将几个 decorator 链接在一起是有意义的:
清单 4. 链接 decorator

@synchronized
@logging
def myfunc(arg1, arg2, ...):
  # ...do something
# decorators are equivalent to ending with:
#  myfunc = synchronized(logging(myfunc))
# Nested in that declaration order

Decorator 只是一个语法糖,如果您过于急切,那么它就会使您搬起石头砸了自己的脚。decorator 其实就是一个至少具有一个参数的函数 —— 程序员要负责确保 decorator 的返回内容仍然是一个有意义的函数或方法,并且实现了原函数为使连接有用而做的事情。例如,下面就是 decorator 两个不正确的用法:
清单 5. 没有返回函数的错误 decorator

>>> def spamdef(fn):
...   print "spam, spam, spam"
...
>>> @spamdef
... def useful(a, b):
...   print a**2 + b**2
...
spam, spam, spam
>>> useful(3, 4)
Traceback (most recent call last):
 File "<stdin>", line 1, in ?
TypeError: 'NoneType' object is not callable

decorator 可能会返回一个函数,但这个函数与未修饰的函数之间不存在有意义的关联:
清单 6. 忽略传入函数的 decorator

>>> def spamrun(fn):
...   def sayspam(*args):
...     print "spam, spam, spam"
...   return sayspam
...
>>> @spamrun
... def useful(a, b):
...   print a**2 + b**2
...
>>> useful(3,4)
spam, spam, spam

最后,一个表现更良好的 decorator 可以在某些方面增强或修改未修饰函数的操作:
清单 7. 修改未修饰函数行为的 decorator

>>> def addspam(fn):
...   def new(*args):
...     print "spam, spam, spam"
...     return fn(*args)
...   return new
...
>>> @addspam
... def useful(a, b):
...   print a**2 + b**2
...
>>> useful(3,4)
spam, spam, spam
25

您可能会质疑,useful() 到底有多么有用?addspam() 真的是那样出色的增强 吗?但这种机制至少符合您通常能在有用的 decorator 中看到的那种模式。

高级抽象简介

根据我的经验,元类应用最多的场合就是在类实例化之后对类中的方法进行修改。decorator 目前并不允许您修改类实例化本身,但是它们可以修改依附于类的方法。这并不能让您在实例化过程中动态添加或删除方法或类属性,但是它让这些方法可以在运行时根据环境的条件来变更其行为。现在从技术上来说,decorator 是在运行 class 语句时应用的,对于顶级类来说,它更接近于 “编译时” 而非 “运行时”。但是安排 decorator 的运行时决策与创建类工厂一样简单。例如:
清单 8. 健壮但却深度嵌套的 decorator

def arg_sayer(what):
  def what_sayer(meth):
    def new(self, *args, **kws):
      print what
      return meth(self, *args, **kws)
    return new
  return what_sayer

相关文章

  • Python模拟伯努利试验和二项分布代码实例

    Python模拟伯努利试验和二项分布代码实例

    这篇文章主要介绍了Python模拟伯努利试验和二项分布代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • Python用for循环实现九九乘法表

    Python用for循环实现九九乘法表

    本文通过实例代码给大家介绍了Python用for循环实现九九乘法表的方法,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-05-05
  • Python进程使用内存后不释放的解决

    Python进程使用内存后不释放的解决

    这篇文章主要介绍了Python进程使用内存后不释放的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Pycharm远程连接服务器并运行与调试

    Pycharm远程连接服务器并运行与调试

    本篇文章介绍一下 Pycharm 如何配置远程连接信息,使其能够在本地使用服务器上的GPU等硬件资源,并在本地完成代码的运行与调试,感兴趣的可以了解一下
    2021-08-08
  • Python代码显得Pythonic(区别于其他语言的写法)

    Python代码显得Pythonic(区别于其他语言的写法)

    这篇文章主要介绍了Python代码显得Pythonic(区别于其他语言的写法),对于字符串连接,相比于简单的+,更pythonic的做法是尽量使用%操作符或者format函数格式化字符串,感兴趣的小伙伴和小编一起进入文章了解更详细相关知识内容吧
    2022-02-02
  • django 扩展user用户字段inlines方式

    django 扩展user用户字段inlines方式

    这篇文章主要介绍了django 扩展user用户字段inlines方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • python实现图片压缩代码实例

    python实现图片压缩代码实例

    这篇文章主要介绍了python实现图片压缩代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • python重试装饰器的简单实现方法

    python重试装饰器的简单实现方法

    今天小编就为大家分享一篇python重试装饰器的简单实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01
  • 对pandas replace函数的使用方法小结

    对pandas replace函数的使用方法小结

    今天小编就为大家分享一篇对pandas replace函数的使用方法小结,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • 致Python初学者 Anaconda入门使用指南完整版

    致Python初学者 Anaconda入门使用指南完整版

    相信大多数 Python 的初学者们都曾为环境问题而头疼不已,但你并不孤独,大家都是这么折腾过来的。为了在入门时少走弯路,并且让高涨的积极性不至于太受打击,这里推荐使用 Anaconda 来管理你的安装环境和各种工具包
    2018-04-04

最新评论