【问题标题】:Why does the Pythons __call__ return the same Decorator instance?为什么 Python 的 __call__ 返回相同的装饰器实例?
【发布时间】:2021-03-25 21:34:27
【问题描述】:
class Decorator:
def __init__(self, C):
    self.C = C

def __call__(self, *args):
    self.wrapped = self.C(*args)
    return self


@Decorator
class C:
    def __init__(self, attr):
        self.attr = attr

x = C('hello')
y = C('world')
print(x)
print(y)

结果:

<__main__.Decorator object at 0x000000000056A400>
<__main__.Decorator object at 0x000000000056A400>

我不明白为什么在方法 __call__ 中返回了类 Decorator 的相同实例。

【问题讨论】:

  • 你写了return self;为什么你会期望它返回一个不同的对象?
  • 你用@Decorator装饰了一个类,所以你的代码执行一次Decorator构造函数来创建一个Decorator对象。它不能等同于创建两个Decorator 对象的任何代码。
  • 它指的是您的代码创建的Decorator 的一个单一实例; Decorator 的实例也绑定到名称 C
  • 你得到一个 decorator 实例,但有两个 C 实例
  • 你可以通过用它装饰更多的东西来创建更多 Decorator 类的实例——所以它不是单例,不。 C 类也不是单身人士;您的 __call__ 方法每次都会创建它的一个新实例。

标签: python decorator call


【解决方案1】:

装饰器“绑定”到类,而不是实例。加个计数器就更清楚了:

class Decorator:
    count = 0

    def __init__(self, C):
        self.C = C

    def __call__(self, *args):
        self.count += 1
        self.wrapped = self.C(*args)
        print('Decorator counter: %d' % self.count)
        return self


@Decorator
class C:
    count = 0

    def __init__(self, attr):
        self.count += 1
        self.attr = attr
        print(self)
        print('C counter: %d' % self.count)


x = C('hello')
y = C('world')
print(x)
print(y)

输出:

<__main__.C object at 0x1070ec050>
C counter: 1 # adds one to each instance
Decorator counter: 1
<__main__.C object at 0x1070ec0d0>
C counter: 1 # adds one to each instance
Decorator counter: 2 # sums up!
<__main__.Decorator object at 0x1070e7fd0>
<__main__.Decorator object at 0x1070e7fd0>

【讨论】:

  • 好的,所以在这种情况下,装饰器总是单例的。谢谢!
猜你喜欢
  • 2013-10-30
  • 2023-03-23
  • 2018-11-20
  • 1970-01-01
  • 2020-02-10
  • 2019-12-11
  • 2020-06-22
  • 1970-01-01
  • 2020-02-03
相关资源
最近更新 更多