winston 发表于 2012-12-27 16:45:08

Python的装饰器

Python装饰器

什么是Python的装饰器?装饰器的英文名是decorator,它的本质是利用动态语言的特性,改变、过滤、记录已有类、函数的行为或对象,它可以进行命名的重新绑定,借此进行对象的管理。

为什么使用装饰器?语法明确清楚,使用方便。
装饰器可以是一个函数或者类,它是一个返回可调用对象的可调用对象。就是说,调用它,返回一个可以再次调用的对象。而这个对象参数经常有所不同。这样就把原来的对象“包裹”了起来。

它实际上把下面展示的第一行映射为第二行:
func(6)
decorator(func)(6)
也相当于:
@decorator
class c:
--->
class c:
...
C = decorator(c)
...
众所周知,Python是一种动态语言,所谓动态语言,是相对于编译型的静态语言 - C/C++等语言来说的。动态,就是可以在运行时改变程序结构、对象的类型,产生和删除函数等,而这些在编译型的语言看来是很难做到甚至是做不到的。

装饰器利用了python语言的几个特性:嵌套函数、闭包。函数在python语言中,是“一等对象”,所谓“一等对象”,就是说函数与其它类型的对象没有根本差别,可以跟其它类型对象一样,产生、传递、赋值、计算、删除。这种概念上的抽象带来了极大的优点和进步,能轻易的做到过去的语言很难做到的任务。闭包则利用了嵌套函数这点特性,扩展出一个新的概念:生命周期链。就是在闭包代码执行的过程中,代码的上下文环境构成了一套“微型代码环境”包,里面的自变量并不随着本地函数作用域的退出而清除,而是在更大范围上,构成了作用域范围。

基于这些特性,装饰器可以执行几种任务:
装饰函数,对装饰的函数进行注册登记、检查管理,然后返回这个函数。
      def decorator(f):
            #process function f
            return f
      @decorator
      def func():
            ...
    装饰函数,插入逻辑拦截函数的随后调用,然后返回一个不同的函数。
      def decorator(f):
            def wrapper(*args):
                #use f and args
                #f(*args) calls original function
            return wrapper #返回新的对象
      @decorator
      def func(x,y)
            ...
      func(1,2)
    装饰类,函数和类的组合使用。注意,装饰器的调用在创建实例的时候就开始了。
    def decorator(c):
      #process class c
      return c
    @decorator
    class c:...
    装饰类,返回不同的类对象。
    def decorator(cls):
      class wrapper:
            def __init__(self,*args):
                self.wrapped = cls(*args)
            def __getattr__(self,name):
                return getattr(self.wrapped,name)
      return wrapper

    @decorator
    class C:
      def __init__(self,x,y):
            self.attr = 'spam'

    x = C(6,8)

   
装饰器可以使用参数,这些参数实际上传递给了真正返回的可调用对象。装饰器参数实际上在装饰发生前就解析了,保持状态一直到供随后的调用使用。
装饰器参数往往意味着可调用对象的三个层级:接受装饰器参数的一个可调用对象,它返回一个可调用对象作为装饰器。这个装饰器返回一个可调用对象来处理对最初的函数和类的调用。这三个层级每一个都可能是一个函数或者类,并且可能以作用域或类属性的形式保存了状态。


装饰器还可以嵌套使用,
@A
@B
@C
def f():
    ...
相当于:f = A(B(C(f)))

更多装饰器的例子:
例子1:
class tracer:
    def __init__(self,func):
      self.calls = 0
      self.func = func
    def __call__(self, *args):
      self.calls += 1
      print('call %s to %s' % (self.calls,self.func.__name__))
      self.func(*args)
@tracer
def spam(a,b,c):
    print(a + b + c)

spam(1,2,3)

执行过程:
@tracer语句-> class tracer:__init__; spam(1,2,3)函数调用 -> class tracer:__call__(xxxx)-> function spam(1,2,3)


例子2:

instance = {}
def getInstance(aClass, * args):
    if aClass not in instance:
      instance = aClass(*args)
    return instance
def singleton(aClass):
    def onCall(*args):
      return getInstance(aClass, *args)
    return onCall

@singleton
class Person:
    def __init__(self,name):
      self.name = name
    def pay(self):
      return 1000

bob = Person('bob')
print(bob.name,bob.pay())

sue = Person('Sue')
print(sue.name, sue.pay())








      






页: [1]
查看完整版本: Python的装饰器