Reputation: 968
class Human:
def __init__(self) -> None:
self.name = None # type: str
def introduce(self):
print("I'm " + self.name)
class Alice(Human):
def __init__(self) -> None:
super().__init__()
self.name = "Alice"
class Bob(Human):
def __init__(self, rude: bool) -> None:
super().__init__()
self.rude = rude
@property
def name(self) -> str:
return "BOB!" if self.rude else "Bob"
if __name__ == '__main__':
alice = Alice()
alice.introduce()
bob = Bob(rude=True)
bob.introduce()
In the code above, there is an abstract Human
class (in reality it is not a human and has more complex methods, not related to the problem). Most of its implementations would set their names by simply assigning a string to the name
attribute (just as Alice
). But there are few exceptions, like Bob
, when there is more complex logic assigned (the value depends on the object state in the moment of resolving).
Therefore in Bob
class I created a custom getter for the name
property. But as an effect, it is impossible to create a class instance, because invoking the superconstructor results in the following error.
AttributeError: can't set attribute
And it is impossible to add a naive setter as well.
@name.setter
def name(self, name: str):
self.name = name
Why? Because it would result in an infinite loop. How to solve that issue?
Upvotes: 0
Views: 348
Reputation: 21
For class Bob
I would have used something like this in this case:
@name.setter
def name(self, name: str):
self._name = name
Afterwards you can do whatever you want in the more complex getter with the internal value. Or did I get the question wrong?
Executing the code would give:
I'm Alice
I'm BOB!
Upvotes: 1
Reputation: 134
why not make a dummy setter
@name.setter
def name(self, value):
pass
When self.name = None
is executed it will call this setter and actually do nothing
Upvotes: 2
Reputation: 1839
If you're certain that your subclasses will assign name
, then you can leave out the assignment in the parent constructor. Right now, Human
is attempting to set to name
, when there is no setter. If you removed it from the Human
constructor, then Human
can look like this:
class Human:
def introduce(self):
print("I'm " + self.name)
Upvotes: 1