Python如何解析装饰器名称

时间:2013-07-23 13:12:11

标签: python decorator python-decorators

我有以下代码:

import threading
from functools import wraps
class Synchronized(object):
    def __init__(self):
        self.lock = threading.Lock()

    def synchronized(f):
        @wraps(f)
        def wrapper(self, *args, **kwargs):
            with self.lock:
                print "here"
                return f(self, *args, **kwargs)
        return wrapper

    @synchronized
    def go(self):
        print 1

class B(Synchronized):
    @synchronized
    def foo(self):
        return 1

此代码在导入抱怨时失败:

  File "a.py", line XXX, in B
    @synchronized
NameError: name 'synchronized' is not defined

但是,如果我注释掉B并且只使用Syncrhonized().go(),那么效果很好。

问题: python如何知道基类中的@synchronized是什么,但未能在其派生词中解析它?

1 个答案:

答案 0 :(得分:4)

synchronized被定义为Synchronized 的类主体中的一个函数

类主体像函数一样执行以定义类;生成的本地名称空间用于形成类属性。这就是synchronizedSynchronized上用作装饰器时go内的本地名称的原因。您可以将其与定义函数内部的装饰器进行比较,然后尝试将其应用于该函数的外部;它不起作用,因为装饰器是局部变量。

您可以在类@Syncronized.synchronized.im_func中使用B.im_func从方法包装器中解包该函数):

class B(Synchronized):
    @Synchronized.synchronized.im_func
    def foo(self):
        return 1

更好的是,不要在所有的类中定义装饰器,而是在Synchronized 之外定义它。毕竟,这不是一种方法:

def synchronized(f):
    @wraps(f)
    def wrapper(self, *args, **kwargs):
        with self.lock:
            print "here"
            return f(self, *args, **kwargs)
    return wrapper

class Synchronized(object):
    def __init__(self):
        self.lock = threading.Lock()

    @synchronized
    def go(self):
        print 1

class B(Synchronized):
    @synchronized
    def foo(self):
        return 1