Override de Propriedade

Asked

Viewed 70 times

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 theme still a little obscure with few examples and little information about it. Follow 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 being:

>>> Matheus Saraiva

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

  • I just realized that the result is being this as the initializer of Person is not going through the property, instead I am assigned the value directly to the variable self.__name = name, however, if I change to self.name = name I get the error saying 'super' does not have an attribute 'name'.

2 answers

1


@Matheussaraiva, I see two problems in your code, and they relate to the concept of getters and setters.

First point, is that you’re calling in your init the hidden variable to make the assignment, and therefore the setter will not be called, and so, the overwrite will never get the chance to be assigned, unless in your code you do some sort of assignment ms.name = "x", when effectively the setter will rotate.

To solve this, just change in init class Person the self.__name = name for self.name = name.

The second problem is deeper, and I myself did several tests to be able to solve it. I even found a old bug Python related to the hierarchy of setters and getters.

These questions are with your code super().name = 'override':
- The first thing, and more serious, is that when you call super(), without explaining the arguments, your program will pull the values self.__class__, self as arguments, ie the current class, in the case Myself and the instantiated object in the ms. But how are we talking about a class property, by leaving the self As a 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 clarify the arguments of the super
- The second is that you did a direct assignment instead of using the method fset(), which is the one that defines, behind the scenes, what the decorator @property is doing while defining the methods of setters and getters, then it needs to be explicit.
Using these fixes in your code, it gets fixed like this:

@Person.name.setter
def name(self, value):
    super(self.__class__, self.__class__).name.fset(self, 'override')
  • 1

    Thanks! Some features are new to me as is the case of function fset, Nor did I know that super() received parameters, I will read the documentation about them.

0

[TL;DR]

Look at 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 on repl it..

Browser other questions tagged

You are not signed in. Login or sign up in order to post.