Radosław Łazarz
Radosław Łazarz

Reputation: 968

Create property with no implemented setter

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

Answers (3)

Mauro
Mauro

Reputation: 21

For class BobI 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

odrling
odrling

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

szxk
szxk

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

Related Questions