【问题标题】:Decorate a class in Python by defining the decorator as a class通过将装饰器定义为类来装饰 Python 中的类
【发布时间】:2012-04-11 23:09:02
【问题描述】:

通过将装饰器定义为类来装饰类的简单示例是什么?

我正在尝试使用 PEP 3129 实现 Python 2.6 中已实现的功能,除了使用类而不是函数,正如 Bruce Eckel 解释的 here

以下作品:

class Decorator(object):
    def __init__(self, arg):
        self.arg = arg

    def __call__(self, cls):
        def wrappedClass(*args):
            return cls(*args)
        return type("TestClass", (cls,), dict(newMethod=self.newMethod, classattr=self.arg))

    def newMethod(self, value):
        return value * 2

@Decorator("decorated class")
class TestClass(object):
    def __init__(self):
        self.name = "TestClass"
        print "init %s"%self.name

    def TestMethodInTestClass(self):
        print "test method in test class"

    def newMethod(self, value):
        return value * 3

除了,在上面,wrappedClass 不是一个类,而是一个被操作以返回类类型的函数。我想编写如下相同的可调用对象:

def __call__(self, cls):
        class wrappedClass(cls):
            def __init__(self):
                ... some code here ...
        return wrappedClass

如何做到这一点?

我不完全确定 """...这里有一些代码..."""

【问题讨论】:

  • 您是否尝试过您自己发布的代码?它应该可以工作。
  • 使用该功能的第一部分确实有效。不过,我如何将 WrappedClass 写成真正的类?
  • 你的装饰师应该做什么?在不知道这段代码应该做什么的情况下,我无法告诉你哪些代码必须进入“这里的一些代码”。
  • 我想用一个类来实现一个函数可以实现的东西。我知道这可以做到,但找不到任何例子来说明这一点
  • 我不明白。第二个 sn-p 中的代码应该可以正常工作。您可以将 any 代码放在“此处的某些代码”所在的位置。我现在应该如何知道这段代码应该做什么?如果您不想覆盖__init__(),那就不要。如果你确实想覆盖它,你显然想以某种方式改变它的行为。我在问:以什么方式?

标签: python decorator


【解决方案1】:

如果你想覆盖new_method(),就这样做吧:

class Decorator(object):
    def __init__(self, arg):
        self.arg = arg
    def __call__(self, cls):
        class Wrapped(cls):
            classattr = self.arg
            def new_method(self, value):
                return value * 2
        return Wrapped

@Decorator("decorated class")
class TestClass(object):
    def new_method(self, value):
        return value * 3

如果您不想更改__init__(),则无需覆盖它。

【讨论】:

  • 有什么场景我们应该装饰类而不是使用类继承?
【解决方案2】:

在此之后,NormalClass 类成为 ClassWrapper instance

def decorator(decor_arg):

    class ClassWrapper:
        def __init__(self, cls):
            self.other_class = cls

        def __call__(self,*cls_ars):
            other = self.other_class(*cls_ars)
            other.field += decor_arg 
            return other

    return ClassWrapper

@decorator(" is now decorated.")
class NormalClass:
    def __init__(self, name):
        self.field = name

    def __repr__(self):
        return str(self.field)

测试:

if __name__ == "__main__":

    A = NormalClass('A');
    B = NormalClass('B');

    print A
    print B
    print NormalClass.__class__

输出:

A is now decorated. <br>
B is now decorated. <br>
\__main__.classWrapper

【讨论】:

  • 您忘记在 call 方法中返回“其他”变量
猜你喜欢
  • 2021-07-16
  • 2011-07-25
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 2015-10-23
  • 2012-02-09
  • 2019-09-20
  • 2010-10-14
相关资源
最近更新 更多