Python Forum

Full Version: @property vs __set__ / __get__ and __setattr__ / __getattr__
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am new to Python and trying to get my head around Python OOP. I can see that using separate getter and setter is a bad approach and becomes tedious when there are a large amount of user accessible properties. The "proper" way to do this in Python therefore is to use @property and @propertyname.setter decorators.

While I understand the use of @property and @propertyname.setter, the presence of __set__ / __get__ and __setattr__ / __getattr__ have me scratching my head. Why do these even exist if they are not supposed to be used? Also, why there are two pairs and not just one pair of __set__ / __get__.

Finally, do we use the decorator @property or use method Property()? The method needs one to pass the methods that correspond to the getter, setter and deleter for the property
(Jun-15-2021, 12:15 PM)okhajut Wrote: [ -> ]Finally, do we use the decorator @property or use method Property()?
It's most common to use @property decorator.
As you mention should not just use getter and setter in Python,if only need simple attribute accesses.
A example.
class Homework:
    def __init__(self):
        self.grade = 0
Use
>>> kent = Homework()
>>> # Set
>>> kent.grade = 90
>>> # Get
>>> kent.grade
90
# Set
>>> kent.grade = 110
# Get
>>> kent.grade
110
As see so do getter and setter work fine here,do not need to write own method for this.
Only if need more that simple attribute access should use property.
Also an of aspect @property decorator is that original implementation can be made backward compatible.
See that the call is just the same,but now can not do 110.
class Homework:
    def __init__(self):
        self._grade = 0

    @property
    def grade(self):
        return self._grade

    @grade.setter
    def grade(self, value):
        if not (0 <= value <= 100):
            raise ValueError('Grade must be between 0 and 100')
        self._grade = value
Use.
>>> kent = Homework()
>>> kent.grade = 90
>>> kent.grade
90
>>> 
>>> kent.grade = 110
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "G:\div_code\my_files\homework.py", line 12, in grade
    raise ValueError('Grade must be between 0 and 100')
ValueError: Grade must be between 0 and 100
Python Is Not Java
Quote:Getters and setters are evil. Evil, evil, I say! Python objects are not Java beans.
Do not write getters and setters.
This is what the ‘property’ built-in is for.
And do not take that to mean that you should write getters and setters, and then wrap them in ‘property’.
That means that until you prove that you need anything more than a simple attribute access, don’t write getters and setters.
They are a waste of CPU time, but more important, they are a waste of programmer time.
Not just for the people writing the code and tests, but for the people who have to read and understand them as well.

In Java, you have to use getters and setters because using public fields gives you no opportunity to go back and change your mind later to using getters and setters.
So in Java, you might as well get the chore out of the way up front.
In Python, this is silly, because you can start with a normal attribute and change your mind at any time, without affecting any clients of the class.
So, don’t write getters and setters.
Can look at his Thread how it should not be done,i was little frustrating that probably a teacher that comes from Java and lean student to do it just then same way in Python.