Valentin Fabianski
Valentin Fabianski

Reputation: 706

Override setter with property: TypeError: 'int' object is not callable

I am getting the following error:

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

And here is the code:

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

I saw that post class method TypeError "Int object not callable" but it did not help me

Upvotes: 0

Views: 670

Answers (3)

Valentin Fabianski
Valentin Fabianski

Reputation: 706

Another answer seems to be the best one:

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

Upvotes: 0

Valentin Fabianski
Valentin Fabianski

Reputation: 706

The best I have come up is this:

  1. If there is no need to override the getter then you can prefix by parent class name
  2. No code in setter: setters only call other methods

    2.a Defined instance methods which do the setter instructions

    2.b Which are called by the setters

    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
    

Upvotes: 0

William Afonso
William Afonso

Reputation: 96

Python properties are non-polymorphic : https://www.artima.com/forums/flat.jsp?forum=122&thread=153649

Upvotes: 1

Related Questions