【问题标题】:How does Python resolve decorator namesPython如何解析装饰器名称
【发布时间】:2013-07-23 13:12:10
【问题描述】:

我有以下代码:

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 是什么,但无法在其派生类中解析它?

【问题讨论】:

  • 为什么要同步成为一个方法,而不是一个函数?
  • 因为我想将它保留在类中以便更好地组织代码

标签: python decorator python-decorators


【解决方案1】:

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

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

您可以在B 类中使用@Syncronized.synchronized.im_func.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

【讨论】:

  • 感谢您的解释。是的,我知道我可以在类之外定义装饰器,但是如果将其用作辅助模式,则需要导入两件事。或者,我可以用 @staticmethod 装饰 synchronized 并仅在派生类中使用它。
  • 你也可以在基础中使用它:@synchronize.__func__.
猜你喜欢
  • 1970-01-01
  • 2012-02-28
  • 2016-10-10
  • 1970-01-01
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-10
相关资源
最近更新 更多