1

I am messing around with the property descriptor in python, but an interesting error (at least for me) popped up (recursionerror).This is the code that caused it

 class Employer: def __init__(self, age, name): self.age = age self.name = name def get_age(self): return self.age def set_age(self, value): if value > 30: raise ValueError("Our company doesn't want old people") self.age = value def deleter(self): del self.age age = property(get_age, set_age, deleter) emp = Employer(20, "Alex") 

Now, after I changed self.age in the setter method to self._age and did the same thing in the getter and deleter methods, everything worked fine, but I don’t really get why.I looked at the documentation but I don’t really understand this : "Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls.” When I get the recursion error I reckon that something is being broken, but it doesn’t seem to me.Follow my reasoning:

  1. I define the attribute which is goint to be stored in a dictionary
  2. I modify that attribute using self.attribute_name I mean it seems that something is already running when i try to modify the attribute name using my approach.Could someone link the concept of private variables with the property descriptor, because probably that’s where the problem lies.Thank you for your attention.

2 Answers 2

3

self.age is a descriptor with the setter logic set_age. set_age is called whenever self.age = ... is performed.

Since an assignment to self.age happens in set_age, you get infinite recursion.

Sign up to request clarification or add additional context in comments.

13 Comments

@Not_here_to_play I think you understood the problem. I don't quite understand your question about self._age, but maybe this helps: the point of self._age is to store the age value in a "normal" instance variable that does not run getter or setter logic when accessed (unlike self.age).
@Not_here_to_play so self.age calls functions when being accessed or set. These functions may do something with self._age, where the actual age value is stored, "hidden" from the user.
@Not_here_to_play self._age is a normal instance variable that you did not define as a property, so no getter or setter logic is run when you get or set it. Rename self._age to self.the_numeric_age_value in your head. It's completely decoupled from self.age, you just happen to access/set in the body of get_age or set_age.
@Not_here_to_play "how on earth do i get self._age and not self.age when I run print(self.age)" <- by returning self._age in get_age.
@Not_here_to_play _age is not a property, it's a normal instance variable. If it was a property like age, it would have its own setters and getters.
|
1

You can do it like this to avoid name clashes.

class Employer: def __init__(self, age, name): self.__age = age self.__name = name @property def age(self): return self.__age @age.setter def age(self, value): if value > 30: raise ValueError("Our company doesn't want old people") self.__age = value @age.deleter def age(self): del self.__age 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.