【问题标题】:Using the @property decorator and dunder methods使用 @property 装饰器和 dunder 方法
【发布时间】:2021-11-27 16:04:09
【问题描述】:

在调试一些代码时,我使用 @property 装饰器发现了一个意外行为。简化版如下:

class TestClass:

    @property
    def __len__(self):
        return 6


test_instance = TestClass()
print(len(test_instance))

我希望这会打印 6,但我得到一个 TypeError:TypeError: 'int' object is not callable

没有属性装饰器,这可以正常工作。我也可以print(test_instance.__len__) 没有问题。我正在努力弄清楚为什么会出现这种情况,并希望有人能用简单的术语来解释它。

编辑: 对于非 dunder 方法,这也可以按我的预期工作:

class TestClass:

    @property
    def foobar(self):
        return 6


test_instance = TestClass()
print(test_instance.foobar)

6 按预期打印。我的理解是len(Class) 是调用__len__ 方法的语法糖,这就是我在这里感到困惑的原因

【问题讨论】:

  • 你为什么期望它打印6?您希望它如何工作?
  • 你为什么要把 dunder 方法变成属性?你到底想解决什么? len(obj) 致电 obj.__len__()。试图使__len__ 成为属性本质上等同于6()(至少在这种情况下),因此关于int 的错误不是callable
  • 属性用于编写一些东西,就好像它是一个属性一样,并让它调用一个方法。如果获取对象长度的正常方法是obj.__len__,那么您的尝试将起作用。但由于它通常是一种方法,因此您不需要属性。

标签: python python-decorators


【解决方案1】:

len 尝试调用 test_instance.__len__,但现在它是一个属性,该属性访问的计算结果为 6,而不是一个函数。

如果您只是希望TestClass 的实例具有硬编码长度为 6,请不要使用属性。

class TestClass:
    def __len__(self):
        return 6

【讨论】:

  • 谢谢,我想我可能误解了属性的用途。我不想要一个固定值 - 这足以证明问题。实际上,我的类方法需要一段时间来计算,所以我一直在使用@cached_property 来节省不必要的重新计算。我想我以后应该小心消除@cache@cached_property 之间的歧义。
猜你喜欢
  • 2022-01-18
  • 1970-01-01
  • 2018-04-04
  • 2013-01-19
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多