【问题标题】:Override setter with property: TypeError: 'int' object is not callable使用属性覆盖 setter:TypeError:'int' object is not callable
【发布时间】:2020-04-02 02:49:07
【问题描述】:

我收到以下错误:

Traceback (most recent call last):
  File ".../TEST.py", line 34, in <module>
    b.level = 12    # Error
  File ".../TEST.py", line 23, in level
    super().level(self, new_level)
TypeError: 'int' object is not callable

这里是代码:

class A:
    def __init__(self):
        self._level = 0

    @property
    def level(self):
        return self._level

    @level.setter
    def level(self, new_level):
        self._level = new_level

class B(A):
    def __init__(self):
        super().__init__()

    @property
    def level(self):
        return self._level

    @level.setter
    def level(self, new_level):
        super().level(self, new_level)



a = A()
print(a.level)  # --> 0
a.level = 12
print(a.level)  # --> 0

b = B()
print(b.level)  # --> 12
b.level = 12    # Error
print(b.level)  # never reached

我看到了那个帖子class method TypeError "Int object not callable",但对我没有帮助

【问题讨论】:

  • 原因是super().level 不是函数。
  • 注意,关于superproperty/descriptor 设置器有一个未解决的问题:bugs.python.org/issue14965
  • DustyPosa,但它应该是一个函数。我在另一堂课上写过同样的东西,效果很好。我应该更改哪些代码行?

标签: python oop properties getter-setter super


【解决方案1】:

【讨论】:

  • 谢谢,我现在知道问题的原因是什么
【解决方案2】:

我想出的最好的是:

  1. 如果不需要覆盖 getter,则可以前缀为父类名
  2. setter 中没有代码:setter 只调用其他方法

    2.a 定义执行setter指令的实例方法

    2.b 由setter调用的

    class A:
        def __init__(self):
            self._level = 0
    
        def A_level_setter(self, new_level):      # 2.a
            print('Setter instructions of A')
            self._level = new_level
    
        @property
        def level(self):
            return self._level
    
        @level.setter
        def level(self, new_level):
            self.A_level_setter(new_level)        # 2.b
    
    class B(A):
        def B_level_setter(self, new_level):      # 2.a
            print('Setter instructions of B')
            self.A_level_setter(new_level)
    
        @A.level.setter                           # 1.
        def level(self, new_level):
            self.B_level_setter(new_level)        # 2.b
    
    class C(A):
        pass
    
    
    a = A()
    print(a.level)  # 0
    b = B()
    print(b.level)  # 0
    c = C()
    print(c.level)  # 0
    
    
    a.level = 1     # Setter instructions of A
    print(a.level)  # 1
    
    b.level = 2     # Setter instructions of A
                    # Setter instructions of B
    print(b.level)  # 2
    
    c.level = 3     # Setter instructions of A
    print(c.level)  # 3
    

【讨论】:

    【解决方案3】:

    另一个答案似乎是最好的:

    class B(A):
        @A.level.setter
        def level(self, new_level):
            super(B, type(self)).level.fset(self, new_level)
    

    【讨论】:

      猜你喜欢
      • 2021-10-22
      • 1970-01-01
      • 2017-04-06
      • 2013-03-30
      • 2015-01-05
      • 2018-07-23
      • 2018-04-14
      • 2019-11-11
      • 1970-01-01
      相关资源
      最近更新 更多