如何在类中创建新的装饰器而不显式导入它们?

oul*_*enz 6 python metaclass python-3.x python-decorators

是否可以修改一个类以使某个方法装饰器可用,而不必显式导入它而不必添加前缀(@something.some_decorator):

class SomeClass:

    @some_decorator
    def some_method(self):
        pass
Run Code Online (Sandbox Code Playgroud)

我不认为这是可能的类装饰器,因为这应用太晚了.看起来更有希望的选项是使用元类,但我不确定如何,我的猜测是我必须some_decorator被引入到名称空间中SomeClass.

感谢@MartijnPieters指出staticmethod并且classmethod是内置插件.我原以为他们是type机器的一部分.

为了清楚起见,我没有任何明确的用例,我只是好奇这是否可能.

ADDENDUM,现在问题已得到解答.我之所以超越简单地在本地导入或定义装饰器的原因,是因为我定义了一个装饰器,只有在某个对象上初始化某个容器属性时才会起作用,而我正在寻找一种方法来强制执行此操作装饰的可用性.我最终检查属性是否存在,如果没有在装饰器中初始化它,这可能是这里较小的邪恶.

Mar*_*ers 7

是的,在Python 3中,您可以使用元类__prepare__钩子.它应该返回一个映射,它构成了类体的本地命名空间的基础:

def some_decorator(f):
    print(f'Decorating {f.__name__}')
    return f

class meta(type):
    @classmethod
    def __prepare__(mcls, name, bases, **kw):
        return {'some_decorator': some_decorator}

class SomeClass(metaclass=meta):
    @some_decorator
    def some_method(self):
        pass
Run Code Online (Sandbox Code Playgroud)

运行以上产生

Decorating some_method
Run Code Online (Sandbox Code Playgroud)

但是,你不应该使用它.正如PythonZen所说:显式优于隐式,并且在您的类中引入魔术名称很容易导致混淆和错误.导入元类与导入装饰器没有什么不同,您将一个名称替换为另一个名称.

在创建类主体后,类装饰器仍然可以将其他装饰器应用于类上的方法.该@decorator语法只是语法糖name = decorator(decorated_object),以后可以随时上应用装饰用name = decorator(name),或在一类背景下,作为cls.name = decorator(cls.name).如果您需要选择应该应用的方法,您可以选择方法名称,方法上设置的属性或方法的文档字符串等条件.或者直接在方法上使用装饰器.