Prefer properties. It's what they're there for.

The reason is that all attributes are public in Python. Starting names with an underscore or two is just a warning that the given attribute is an implementation detail that may not stay the same in future versions of the code. It doesn't prevent you from actually getting or setting that attribute. Therefore, standard attribute access is the normal, Pythonic way of, well, accessing attributes.

The advantage of properties is that they are syntactically identical to attribute access, so you can change from one to another without any changes to client code. You could even have one version of a class that uses properties (say, for code-by-contract or debugging) and one that doesn't for production, without changing the code that uses it. At the same time, you don't have to write getters and setters for everything just in case you might need to better control access later.

Answer from kindall on Stack Overflow
๐ŸŒ
Real Python
realpython.com โ€บ python-getter-setter
Getters and Setters: Manage Attributes in Python โ€“ Real Python
January 20, 2025 - Getter and setter methods allow you to access and mutate non-public attributes while maintaining encapsulation. In Python, youโ€™ll typically expose attributes as part of your public API and use properties when you need attributes with functional behavior.
๐ŸŒ
Python Reference
python-reference.readthedocs.io โ€บ en โ€บ latest โ€บ docs โ€บ property โ€บ setter.html
setter โ€” Python Reference (The Right Way) 0.1 documentation
class C(object): def __init__(self): self._x = None @property def x(self): """I'm the 'x' property.""" return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x
๐ŸŒ
Medium
aignishant.medium.com โ€บ understanding-python-property-decorators-getters-setters-57d6b535e5d2
Understanding Python Property Decorators: Getters, Setters | by Nishant Gupta | Medium
February 23, 2025 - The property decorator in Python is a powerful feature that allows you to define โ€œgetterโ€, โ€œsetterโ€ methods for class attributes without explicitly calling them as methods.
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ getter-and-setter-in-python
Getter and Setter in Python - GeeksforGeeks
July 11, 2025 - The setter method is used to set the age and the getter method is used to retrieve it. In this method, the property() function is used to wrap the getter, setter and deleter methods for an attribute, providing a more streamlined approach.
๐ŸŒ
Python Course
python-course.eu โ€บ oop โ€บ properties-vs-getters-and-setters.php
3. Properties vs. Getters and Setters | OOP | python-course.eu
A method which is used for getting a value is decorated with "@property", i.e. we put this line directly in front of the header. The method which has to function as the setter is decorated with "@x.setter". If the function had been called "f", we would have to decorate it with "@f.setter".
๐ŸŒ
Programiz
programiz.com โ€บ python-programming โ€บ property
Python @property Decorator (With Examples)
A pythonic way to deal with the above problem is to use the property class. Here is how we can update our code: # using property class class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 # getter def get_temperature(self): print("Getting value...") return self._temperature # setter def set_temperature(self, value): print("Setting value...") if value < -273.15: raise ValueError("Temperature below -273.15 is not possible") self._temperature = value # creating a property object temperature = property(get_temperature, set_temperature)
๐ŸŒ
Mimo
mimo.org โ€บ glossary โ€บ python โ€บ property
Python property(): Syntax, Usage, and Examples
A Python property is a special kind of attribute that lets you run code whenever it is accessed, set, or deleted. It allows you to expose what looks like a simple attribute to the user, while hiding the internal logic for getting or setting its value (getters and setters).
Find elsewhere
Top answer
1 of 9
1159

Try this: Python Property

The sample code is:

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        print("getter of x called")
        return self._x

    @x.setter
    def x(self, value):
        print("setter of x called")
        self._x = value

    @x.deleter
    def x(self):
        print("deleter of x called")
        del self._x


c = C()
c.x = 'foo'  # setter called
foo = c.x    # getter called
del c.x      # deleter called
2 of 9
628

What's the pythonic way to use getters and setters?

The "Pythonic" way is not to use "getters" and "setters", but to use plain attributes, like the question demonstrates, and del for deleting (but the names are changed to protect the innocent... builtins):

value = 'something'

obj.attribute = value  
value = obj.attribute
del obj.attribute

If later, you want to modify the setting and getting, you can do so without having to alter user code, by using the property decorator:

class Obj:
    """property demo"""
    #
    @property            # first decorate the getter method
    def attribute(self): # This getter method name is *the* name
        return self._attribute
    #
    @attribute.setter    # the property decorates with `.setter` now
    def attribute(self, value):   # name, e.g. "attribute", is the same
        self._attribute = value   # the "value" name isn't special
    #
    @attribute.deleter     # decorate with `.deleter`
    def attribute(self):   # again, the method name is the same
        del self._attribute

(Each decorator usage copies and updates the prior property object, so note that you should use the same name for each set, get, and delete function/method.)

After defining the above, the original setting, getting, and deleting code is the same:

obj = Obj()
obj.attribute = value  
the_value = obj.attribute
del obj.attribute

You should avoid this:

def set_property(property,value):  
def get_property(property):  

Firstly, the above doesn't work, because you don't provide an argument for the instance that the property would be set to (usually self), which would be:

class Obj:

    def set_property(self, property, value): # don't do this
        ...
    def get_property(self, property):        # don't do this either
        ...

Secondly, this duplicates the purpose of two special methods, __setattr__ and __getattr__.

Thirdly, we also have the setattr and getattr builtin functions.

setattr(object, 'property_name', value)
getattr(object, 'property_name', default_value)  # default is optional

The @property decorator is for creating getters and setters.

For example, we could modify the setting behavior to place restrictions the value being set:

class Protective(object):

    @property
    def protected_value(self):
        return self._protected_value

    @protected_value.setter
    def protected_value(self, value):
        if acceptable(value): # e.g. type or range check
            self._protected_value = value

In general, we want to avoid using property and just use direct attributes.

This is what is expected by users of Python. Following the rule of least-surprise, you should try to give your users what they expect unless you have a very compelling reason to the contrary.

Demonstration

For example, say we needed our object's protected attribute to be an integer between 0 and 100 inclusive, and prevent its deletion, with appropriate messages to inform the user of its proper usage:

class Protective(object):
    """protected property demo"""
    #
    def __init__(self, start_protected_value=0):
        self.protected_value = start_protected_value
    # 
    @property
    def protected_value(self):
        return self._protected_value
    #
    @protected_value.setter
    def protected_value(self, value):
        if value != int(value):
            raise TypeError("protected_value must be an integer")
        if 0 <= value <= 100:
            self._protected_value = int(value)
        else:
            raise ValueError("protected_value must be " +
                             "between 0 and 100 inclusive")
    #
    @protected_value.deleter
    def protected_value(self):
        raise AttributeError("do not delete, protected_value can be set to 0")

(Note that __init__ refers to self.protected_value but the property methods refer to self._protected_value. This is so that __init__ uses the property through the public API, ensuring it is "protected".)

And usage:

>>> p1 = Protective(3)
>>> p1.protected_value
3
>>> p1 = Protective(5.0)
>>> p1.protected_value
5
>>> p2 = Protective(-5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> p1.protected_value = 7.3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 17, in protected_value
TypeError: protected_value must be an integer
>>> p1.protected_value = 101
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 15, in protected_value
ValueError: protectected_value must be between 0 and 100 inclusive
>>> del p1.protected_value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 18, in protected_value
AttributeError: do not delete, protected_value can be set to 0

Do the names matter?

Yes they do. .setter and .deleter make copies of the original property. This allows subclasses to properly modify behavior without altering the behavior in the parent.

class Obj:
    """property demo"""
    #
    @property
    def get_only(self):
        return self._attribute
    #
    @get_only.setter
    def get_or_set(self, value):
        self._attribute = value
    #
    @get_or_set.deleter
    def get_set_or_delete(self):
        del self._attribute

Now for this to work, you have to use the respective names:

obj = Obj()
# obj.get_only = 'value' # would error
obj.get_or_set = 'value'  
obj.get_set_or_delete = 'new value'
the_value = obj.get_only
del obj.get_set_or_delete
# del obj.get_or_set # would error

I'm not sure where this would be useful, but the use-case is if you want a get, set, and/or delete-only property. Probably best to stick to semantically same property having the same name.

Conclusion

Start with simple attributes.

If you later need functionality around the setting, getting, and deleting, you can add it with the property decorator.

Avoid functions named set_... and get_... - that's what properties are for.

๐ŸŒ
DataCamp
datacamp.com โ€บ tutorial โ€บ property-getters-setters
Python Property vs. Getters & Setters | DataCamp
December 18, 2018 - Setters: These are the methods used in OOPS feature which helps to set the value to private attributes in a class. If you are not familiar with the private attributes or private methods in Python, read this DataCamp article. Let's see how you can implement a private attribute in Python. class ...
๐ŸŒ
Reddit
reddit.com โ€บ r/learnpython โ€บ getters and setter in python using property should you use this way?
r/learnpython on Reddit: getters and setter in python using property should you use this way?
March 17, 2020 -

While in all other languages you use getters and setters. In python you apparently do this by using:

  property(getter,setter,..) or with decorators @property

and that's cool and all but then when you go in your code do you do something like this?

property_class = PropertyClass()
property_class.my_property = 20 #actually goes through setter method
property_class.my_property #output: 5 , goes through getter

is it not weird that the output is different even though (without looking into the class) it looks like it didn't go through any methods?


I think I see it as useful when you discover something thats always true about your property and you have to include that without breaking someone elses code. BUT other than that I see it only as being confusing. Which is why I'm gonna continue ignoring using this way by creating 'normal' getters and setters.

I hope someone will give me a good explanation so I can correct myself if I'm wrong.

Top answer
1 of 3
2
C# uses something like Python's property mechanism. Java normally uses standard getters and setters. I seem to recall there was a time you could treat java beans attributes as properties, and that would make sense. Python properties are important because python doesn't really have a private keyword. (The __attribute_name trick is hidden, not really private) So if it's difficult to keep data members private, you can't enforce the use of getters and setters, negating their advantages. So properties allow you to let the user think they are accessing an attribute while affording the protection of a hidden getter and setters.
2 of 3
2
In python you should ordinarily just use attributes, as in: class MyClass: def __init__(self, my_attribute): self.my_attribute = my_attribute my_object = MyClass(4) print(my_object.my_attribute) my_object.my_attribute = 8 As you mentioned, the main purpose of properties is for when you want to change the class so that getting/setting the attribute does something more complicated, without breaking existing code that uses your class. Also they're sometimes used just to give a class a nicer/more understandable API. You can give your classes explicit get_my_attribute and set_my_attribute methods if you really want to, but this makes your code more verbose and doesn't really achieve very much, which is why it isn't done very commonly in python. In some other languages getter and setter functions are either mandatory or strongly recommended because they don't have a way of changing attributes to properties without breaking code, or just because these languages have a philosophy that it's good to be very verbose and explicit about everything. None of those things are true in python. I realize that the exact behaviour of @property is fairly hard to understand if you're new to python (as it involves both decorators and descriptors, which are relatively advanced features), but you can use them without understanding how they work internally. I was very comfortable using properties long before I bothered to actually learn what a descriptor is. You only need to actually understand them if you want to do weird, advanced stuff with them.
๐ŸŒ
Medium
medium.com โ€บ @pijpijani โ€บ understanding-property-in-python-getters-and-setters-b65b0eee62f9
Understanding Property in Python: Getters and Setters | by Pikho | Medium
March 2, 2023 - To achieve this, we can define a setter method for the balance attribute that checks if the value being set is a positive number, and raises an error if it is not. We can also define deposit and withdrawal methods that take in a positive amount as input, and modify the balance attribute accordingly. class BankAccount: def __init__(self, balance): self._balance = balance @property def balance(self): return self._balance @balance.setter def balance(self, value): if not isinstance(value, int) or value < 0: raise ValueError(f"{value} is not a valid input for balance") self._balance = value def dep
๐ŸŒ
Medium
salma-mohamed.medium.com โ€บ getters-setters-and-deleters-in-python-b8ae8fc02662
GETTERS, SETTERS AND DELETERS IN PYTHON | by Salma mohamed | Medium
September 7, 2023 - In this example, the @value.setter decorator allows you to set the value attribute using the setter method. You can add validation or perform other actions when setting the attribute.
๐ŸŒ
Llego
llego.dev โ€บ home โ€บ blog โ€บ python getter and setter methods: a comprehensive guide
Python Getter and Setter Methods: A Comprehensive Guide - llego.dev
July 17, 2023 - By properly designing getters and setters methods following best practices, you can create Python classes with controlled attribute access. Here are some examples demonstrating real-world usage of getter and setter methods: Getters and setters allow validating data before setting it: class Person: def __init__(self, name, age): self.name = name self.age = age @property def age(self): return self._age @age.setter def age(self, value): if value < 0: raise ValueError('Age cannot be negative') self._age = value person = Person('Mary', -10) # Raises ValueError
๐ŸŒ
freeCodeCamp
freecodecamp.org โ€บ news โ€บ python-property-decorator
The @property Decorator in Python: Its Use Cases, Advantages, and Syntax
December 19, 2019 - Specifically, you can define three methods for a property: A getter - to access the value of the attribute. A setter - to set the value of the attribute. A deleter - to delete the instance attribute.
๐ŸŒ
Mathspp
mathspp.com โ€บ blog โ€บ pydonts โ€บ properties
mathspp โ€“ take your Python ๐Ÿ to the next level ๐Ÿš€
As we can see, urllib uses a property setter so that changing the value of full_url updates a few related things: not only does it update the attributes _full_url and fragment; but it also triggers an internal call to _parse() which does further work under the hood! In general, we do not define setter methods like set_name in Python.
๐ŸŒ
DEV Community
dev.to โ€บ hernanchilabert โ€บ understanding-getter-setter-and-private-variables-in-python-9h8
Understanding Getter, Setter and Private variables in Python - DEV Community
January 27, 2024 - Setters are methods used to change or 'set' the value of an object's attributes. They allow for data modification while implementing checks or validations. Private Variables: Attributes prefixed with an underscore (_) or double underscore (__), ...
๐ŸŒ
IONOS
ionos.com โ€บ digital guide โ€บ websites โ€บ web development โ€บ python property
How to use Python property - IONOS
July 20, 2023 - The following code snippet creates a class called โ€œdogโ€ with the attribute โ€œ_nameโ€. While this example has no value in the real world, it helps to illustrate the functionality of Python property and how effective Python properties are. class dog: def __init__(self): self._name = "Bello"Python ยท You may have noticed that the constructor doesnโ€™t have a parameter specifying the dogโ€™s name. Instead, the default value for the dogโ€™s name has been set to โ€œBelloโ€. In this case, you can create an object of the class with the following line of code: ... You can extend your class with specific getter and setter methods.
๐ŸŒ
DEV Community
dev.to โ€บ the1kimk โ€บ function-decorators-in-python-understanding-property-getter-and-setter-methods-3a8e
Function Decorators in Python: Understanding @property, Getter, and Setter Methods - DEV Community
September 22, 2024 - In this example, the getter (get_price()) and setter (set_price()) provide a way to access and modify the _price attribute while enforcing certain rules (like ensuring the price is not negative). The @property Decorator Python offers a more elegant way to manage access to private attributes using the @property decorator.