Property Override

0

According to some examples I found I'm trying to implement an override of a property , but the override does not work. I think this is a still obscure topic with few examples and little information about it. Here is my example:

from abc import ABCMeta, abstractmethod

class Person(metaclass=ABCMeta):

    @abstractmethod
    def __init__(self, name, age):
        self.__name = name
        self.age = age

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, value):
        self.__name = value


class Myself(Person):

    def __init__(self, name, age, tel):
        super().__init__(name, age)
        self.tel = tel

    @Person.name.setter
    def name(self, value):
        super().name = 'override'


class Wife(Person):

    def __init__(self, name, age, tel):
        super().__init__(name, age)
        self.tel = tel



ms = Myself('Matheus Saraiva', 36, '988070350')
wi = Wife('Joice Saraiva', 34, '999923554')

print(ms.name)

If my implementation is correct, the result of print should be:

>>> override

but the result is:

>>> Matheus Saraiva

That is, apparently the override is not working. What is wrong with my implementation?

    
asked by anonymous 08.12.2018 / 13:29

2 answers

1

@MatheusSaraiva, I see two problems in your code, and are related to the concept of getters and setters .

First thing is that you are calling in your init the hidden variable to do the assignment, so the setter will not be called, and so overwrite will never get a chance to be assigned, unless in your code you make some assignment of type ms.name = "x" , when setter will actually run. Home To solve this, just change the init of class Person o self.__name = name to self.name = name .

The second problem is deeper, and I've done several tests myself to get it resolved. I've even encountered a Python old bug related to the setters and getters hierarchy.

These questions are with your code super().name = 'override' :
- The first and most serious thing is that when you call super() , without specifying the arguments, your program will pull the self.__class__, self values as arguments, that is, the current class, in the Myself case, and the object instantiated, in the ms case. But as we're talking about a class property, leaving self as the second argument, it will not recognize class property as part of that object, and therefore the error you saw. For this reason, we need to make explicit the arguments of the super - The second is that you made a direct assignment instead of using the fset() method, which is the one that defines, behind the wipes, what decorator @property is doing when defining the methods of setters and getters , then this needs to be explicit. Home Using these fixes in your code, it corrected looks like this:

@Person.name.setter
def name(self, value):
    super(self.__class__, self.__class__).name.fset(self, 'override')
    
08.12.2018 / 15:19
0

[TL; DR]

See this strategy:

class Foo(object):
    def __init__(self):
        self._foo = None
    @property    
    def foo(self):
        return self._foo
    @foo.setter    
    def foo(self, value):
        self._foo = value

class Bar(Foo):
    @Foo.foo.getter
    def foo(self):
        return self._foo * -1 if type(self._foo)==int else self._foo

bar = Bar()
bar2 = Bar()

# Alterando a propriedade foo da instancia bar atraves da classe Foo
bar.foo = "foo is Foo's property"
print('valor de foo na instancia bar:',bar.foo)
valor de foo na instancia bar: foo is Foo's property

# Alterando a propriedade foo da instancia bar atraves da propria instancia
bar.foo = 99
print('Valor de foo alterado pela instancia: ',bar.foo)
Valor de foo alterado pela instancia:  -99

print('Valor de foo na instancia bar2: ',bar2.foo)
Valor de foo na instancia bar2:  None

See working at repl.it .

    
08.12.2018 / 16:20