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
Answer from Grissiom on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › python › getter-and-setter-in-python
Getter and Setter in Python - GeeksforGeeks
July 11, 2025 - The get_age() method is the getter, which retrieves the value of _age. The set_age() method is the setter, which assigns a value to _age.
🌐
Real Python
realpython.com › python-getter-setter
Getters and Setters: Manage Attributes in Python – Real Python
January 20, 2025 - In this example, the constructor of Label takes two arguments, text and font. These arguments are stored in the ._text and ._font non-public instance attributes, respectively. Then you define getter and setter methods for both attributes.
Discussions

Having a hard time understanding getters and setters
tl;dr - getters and setters are used so that people creating classes can upgrade classes without breaking the code of those that use them. Getters and setters wrap attributes as methods, allowing you to use functionality only available through methods. In Python, we don’t use getters and setters because we have properties, which allow us to make attributes look like methods after the fact. —- To really understand getters and setters means understanding class design, understanding the potential problems with accessing object attributes, understanding why some languages use getters and setters, and finally understanding why we do not need getters and setters in Python. Imagine designing a class, but for a library, a library that people other than you will use. You might design a class once and then you are done with it, but in all likelihood you’ll want to design it in a way where you can upgrade the functionality of it if you need to, so you need to design it in a futureproof way. The most important thing here is to ensure that, when you do upgrade your class with new functionality, you do it in a way that does not break the code of the people that are using it. This is the concept of backwards compatibility - your new class can be used by people who write code against the older class. The importance of this cannot be understated - if you continuously break people’s code every time you upgrade your own, no one will want to use your code, ever. To ensure backwards compatibility, all the things that the people who write code access in your class access must not change. This means - the library import, the class name, the method names, the method parameters, what the method returns, and the attributes of the class - all these must be unchanged. All these aspects make up what is known as the public API of your class, and changing these means breaking backwards compatibility. Now, consider writing code for such a class. For a complicated method, you may wish to refactor its code into multiple sub-methods. Or, you may need to store attributes on your class for reasons of convenience. Having these as part of your public API would be undesirable, partly because the people using your library class do not need to access these, but mostly because if they end up using them, it’ll hamper your ability to upgrade your class in the future. These end up being private methods and attribute - these are not meant to be accessible by people who use your code and you are free to change them should you need to in the future. Languages like C++ and Java let you label functions and attributes as public and private, and people using your library class will be barred from accessing private elements. In Python, there is no public or private - instead you name your private elements giving it a prefix of a single underscore (i.e. self._bar instead of self.bar), and whilst calling code can access these underscore variables, they understand that they generally must not unless they absolutely have to. An important part of protecting your public API is also related to attributes. Attribute access is very limited - you can get a value from an attribute, set a value onto an attribute, and delete an attribute entirely (get, set and delete) - and that’s about it. The problem is, when you upgrade your class, you may end to wanting to do something more. For example, you may want to add validation - i.e. you may want to raise an exception if someone assigns an incorrect value to an attribute. Or you might want to change one attribute to retrieve data from another place - a classic example is a class that provides temperature for something in both Celsius and Fahrenheit, the attribute for one should just get the attribute for the other and then do the C-to/from-F conversion. These are things that can be done only by methods, not attributes, and if you use an attribute as part of your public API you can’t upgrade your class to use these things without breaking the code of those that use your class, because they are accessing an attribute (self.bar) rather than a method (self.bar()). This is where getters and setters come into play. Languages like Java and C++ use these. The concept is simple - have your attributes as private (i.e. self._bar), and then wrap your private attributes in public methods. This is how it looks in Python: def get_bar(self): return self._bar def set_bar(self, val): self._bar = val The people that use your code then use self.get_bar() and self.set_bar() when interacting with your class. Because they are interacting with a method, you can upgrade your class with the above functionality described, without breaking your public API. Getters and setters solve an important problem, but they are not without problems - the biggest being that they are fugly. The people that use your code have to do self.get_bar() rather than self.bar. But the bigger problem is for you, the creator of the class, who has to litter your code with getters and setters, regardless of whether you need them or not. You may never need to upgrade your class in the future, but you’ll need to use getters and setters if you want to expose an attribute, just on the off chance you’ll need it. Python solves this problem with properties. Properties allow for attributes to be converted into methods, but still be accessed as attributes. You, as the creator of a class, use public attributes when required (self.bar). When you upgrade your class, if and only if you need the functionality of a method, you use a property. You convert your public attribute into a private one (self._bar) and then you use the below syntax: @property def bar(self): return self._bar @bar.setter def bar(self, val): self._bar = val People who call your code still access the same way as an attribute (self.bar) but you now have a method under the hood, so you can use functionality that only methods can do, without breaking your public API for your users. And you only add properties when you need them, so you don’t litter your code like you would with getters and setters. More on reddit.com
🌐 r/learnpython
13
8
May 7, 2022
python - Using @property versus getters and setters - Stack Overflow
It can strengthen your self-identification as a Python (not Java) programmer. It can help your job interview if your interviewer thinks Java-style getters and setters are anti-patterns. Traditional getters and setters allow for more complicated data access than simple attribute access. For example, ... More on stackoverflow.com
🌐 stackoverflow.com
How do getters and setters work in Python? - Stack Overflow
In the example above, the constraint is that the age of the person should be positive and less than 120. Implementation of such constraints is not possible without setters. ... Generally speaking you do not code getters and setters in python unless you specifically need them, right now. More on stackoverflow.com
🌐 stackoverflow.com
Use Properties rather than Getters & Setters in Python.

I'm still a Python noob in many ways. I'm trying to grasp the details of this tip and have a few questions.

First, I've never used explicit getter and setter methods. Is this simply a way to get more functionality from the default behavior? Like, in this example, being able to stop someone from overwriting a name once it has been assigned?

Second, I've never used del before in a script. I presume it is a built-in that deletes a property value from an object. My question is why does del hit the @name.deleter code? What ties them together? Is it as simple as this: if customer deleter code exists in the class, it will get called when del is called?

More on reddit.com
🌐 r/pythontips
7
48
October 31, 2012
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.

Top answer
1 of 5
11
tl;dr - getters and setters are used so that people creating classes can upgrade classes without breaking the code of those that use them. Getters and setters wrap attributes as methods, allowing you to use functionality only available through methods. In Python, we don’t use getters and setters because we have properties, which allow us to make attributes look like methods after the fact. —- To really understand getters and setters means understanding class design, understanding the potential problems with accessing object attributes, understanding why some languages use getters and setters, and finally understanding why we do not need getters and setters in Python. Imagine designing a class, but for a library, a library that people other than you will use. You might design a class once and then you are done with it, but in all likelihood you’ll want to design it in a way where you can upgrade the functionality of it if you need to, so you need to design it in a futureproof way. The most important thing here is to ensure that, when you do upgrade your class with new functionality, you do it in a way that does not break the code of the people that are using it. This is the concept of backwards compatibility - your new class can be used by people who write code against the older class. The importance of this cannot be understated - if you continuously break people’s code every time you upgrade your own, no one will want to use your code, ever. To ensure backwards compatibility, all the things that the people who write code access in your class access must not change. This means - the library import, the class name, the method names, the method parameters, what the method returns, and the attributes of the class - all these must be unchanged. All these aspects make up what is known as the public API of your class, and changing these means breaking backwards compatibility. Now, consider writing code for such a class. For a complicated method, you may wish to refactor its code into multiple sub-methods. Or, you may need to store attributes on your class for reasons of convenience. Having these as part of your public API would be undesirable, partly because the people using your library class do not need to access these, but mostly because if they end up using them, it’ll hamper your ability to upgrade your class in the future. These end up being private methods and attribute - these are not meant to be accessible by people who use your code and you are free to change them should you need to in the future. Languages like C++ and Java let you label functions and attributes as public and private, and people using your library class will be barred from accessing private elements. In Python, there is no public or private - instead you name your private elements giving it a prefix of a single underscore (i.e. self._bar instead of self.bar), and whilst calling code can access these underscore variables, they understand that they generally must not unless they absolutely have to. An important part of protecting your public API is also related to attributes. Attribute access is very limited - you can get a value from an attribute, set a value onto an attribute, and delete an attribute entirely (get, set and delete) - and that’s about it. The problem is, when you upgrade your class, you may end to wanting to do something more. For example, you may want to add validation - i.e. you may want to raise an exception if someone assigns an incorrect value to an attribute. Or you might want to change one attribute to retrieve data from another place - a classic example is a class that provides temperature for something in both Celsius and Fahrenheit, the attribute for one should just get the attribute for the other and then do the C-to/from-F conversion. These are things that can be done only by methods, not attributes, and if you use an attribute as part of your public API you can’t upgrade your class to use these things without breaking the code of those that use your class, because they are accessing an attribute (self.bar) rather than a method (self.bar()). This is where getters and setters come into play. Languages like Java and C++ use these. The concept is simple - have your attributes as private (i.e. self._bar), and then wrap your private attributes in public methods. This is how it looks in Python: def get_bar(self): return self._bar def set_bar(self, val): self._bar = val The people that use your code then use self.get_bar() and self.set_bar() when interacting with your class. Because they are interacting with a method, you can upgrade your class with the above functionality described, without breaking your public API. Getters and setters solve an important problem, but they are not without problems - the biggest being that they are fugly. The people that use your code have to do self.get_bar() rather than self.bar. But the bigger problem is for you, the creator of the class, who has to litter your code with getters and setters, regardless of whether you need them or not. You may never need to upgrade your class in the future, but you’ll need to use getters and setters if you want to expose an attribute, just on the off chance you’ll need it. Python solves this problem with properties. Properties allow for attributes to be converted into methods, but still be accessed as attributes. You, as the creator of a class, use public attributes when required (self.bar). When you upgrade your class, if and only if you need the functionality of a method, you use a property. You convert your public attribute into a private one (self._bar) and then you use the below syntax: @property def bar(self): return self._bar @bar.setter def bar(self, val): self._bar = val People who call your code still access the same way as an attribute (self.bar) but you now have a method under the hood, so you can use functionality that only methods can do, without breaking your public API for your users. And you only add properties when you need them, so you don’t litter your code like you would with getters and setters.
2 of 5
7
Generally an object doesn't want you directly accessing or changing it's attributes. This is kinda the point of encapsulation. As such, you generally want to have 'getters' (that GET an objects attributes) and 'setters' (that, as you may guess, SET those attributes.) Say you have a Ball class. Ball has an attribute, diameter. Let's now say softball is an instance of object Ball. You COULD use softball.diameter to access this attribute. In programming it's generally frowned upon, though in Python less so. You might have an object method, say, get_diameter() that returns the diameter. So instead of accessing the variable directly through softball.diameter, you use ball.get_diameter() which is an example of a getter. See if you can imagine how a setter would look. This allows you to encapsulate how attributes are set, changed, accessed, etc, inside the method itself, and is generally considered a good thing.
🌐
Analytics Vidhya
analyticsvidhya.com › home › getter and setter in python
Getter and Setter in Python - Analytics Vidhya
February 17, 2024 - Python provides a built-in property decorator that allows us to define getters and setters concisely and elegantly. The property decorator converts a method into a read-only attribute, and we can define a setter method using the same decorator. class Person: def __init__(self, name): self._name = name @property def name(self): return self._name @name.setter def name(self, value): self._name = value · The above example defines a `Person` class with a private attribute _name.
🌐
TutorialsPoint
tutorialspoint.com › getter-and-setter-in-python
Getter and Setter in Python
January 2, 2020 - class year_graduated: def __init__(self, year=0): self._year = year # getter method def get_year(self): return self._year # setter method def set_year(self, a): self._year = a grad_obj = year_graduated() # Before using setter print(grad_obj.get_year()) # After using setter grad_obj.set_year(2019) print(grad_obj._year) Running the above code gives us the following result: ... In the next example we see how to make the methods private so that the variables in it cannot be manipulated by external calling functions.
🌐
Medium
medium.com › @imshivam077 › day-32-getters-and-setters-f3747f62491e
Day-32 — Getters And Setters. In Python, getters and setters are… | by Shivam Shukla | Medium
December 20, 2023 - Here is an example of a class with both getter and setter: class MyClass: def __init__(self, value): self._value = value @property def value(self): return self._value @value.setter def value(self, new_value): self._value = new_value ...
Find elsewhere
🌐
Programiz
programiz.com › python-programming › property
Python @property Decorator (With Examples)
Let's look at how to implement this as a decorator: class Celsius: def __init__(self, temperature=0): # when creating the object, the setter method is called automatically self.temperature = temperature def to_fahrenheit(self): # convert the temperature to Fahrenheit return (self.temperature ...
🌐
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 · This code is exactly equivalent to the first example. Be sure to give the additional functions the same name as the original property (x in this case.) The returned property also has the attributes fget, fset, and fdel corresponding to the constructor arguments.
🌐
Javatpoint
javatpoint.com › getter-and-setter-in-python
Getter and Setter in Python - Javatpoint
Getter and Setter in Python with python, tutorial, tkinter, button, overview, entry, checkbutton, canvas, frame, environment set-up, first python program, operators, etc.
🌐
Codesarray
codesarray.com › view › Getters-and-Setters-in-Python
Getters and Setters in Python - Codesarray
This is a convention in Python, though not enforced. Getter Methods: get_name() and get_age() return the values of _name and _age, respectively. Setter Methods: set_name() and set_age() allow us to modify _name and _age.
🌐
Ansys
developer.ansys.com › blog › getting-started-classes-python-part-7-getters-and-setters
Getting started with classes in Python Part 7: getters and setters | Ansys Developer Portal
January 21, 2025 - For example, if your class needs to fetch a lot of data from a server to calculate the value a property takes, you can put that fetching code in the getter. That way, the data is loaded only on demand, i.e. it is only fetched and loaded when the method is called and NOT when the class is ...
Top answer
1 of 5
2

The reason to use a getter and setter, is if you want to do something more complex than just set and attribute with foo.bar. In your case, set_age has an

isinstance(new_age, int) & new_age>0 & new_age<120

check, which is not possible to do with a raw attribute. (Side-note: you should use and instead of &.)

Yes, someone can still do p1._age = -1, and then their code won't work, but why would they? It just makes their code not work.

Your get_name function is less useful than the age one. It basically makes name read-only, which might or might not be useful.

When creating setters and getters in Python, it is usual to use the @property decorator. This means the functions can be called as if they were attributes, so instead of p1.get_name() you can just do p1.name. Similarly p1.set_age(3) becomes p1.age = 3.

You probably want to use the age setter in __init__, because then the age of the Person is validated when it is created.

Here is a version that makes these changes (and a couple of other readability improvements).

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, new_age):
        if isinstance(new_age, int) and 0 < new_age < 120:
            self._age = new_age
    
    @property
    def name(self):
        return self._name

    def __str__(self):
        return f"Person[{self.name}] is {self.age}"
    
p1 = Person("Sandeep", 49)
2 of 5
2

You need to tell python how to associate the getter and setter with the actual variable name. To do this you can use the builtin property function like so:

class Person
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def get_age(self):
        return self._age

    def set_age(self, new_age):
        if isinstance(new_age, int) & new_age>0 & new_age<120:
            self._age = new_age

    def get_name(self):
        return self._name
    name = property(get_name)
    age = property(get_age, set_age)

    def __str__(self):
        return 'Person[' + self.name + '] is ' + str(self.age)
    
p1 = Person("Sandeep", 49)

Then instead of referring to _name and _age use name and age

🌐
DataCamp
datacamp.com › tutorial › property-getters-setters
Python Property vs. Getters & Setters | DataCamp
December 18, 2018 - Getters: These are the methods used in Object-Oriented Programming (OOPS) which helps to access the private attributes from a class. 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.
🌐
Medium
medium.com › @sounder.rahul › hands-on-code-python-getter-and-setter-methods-to-access-and-modify-the-private-attributes-52e0b5a25a4b
Hands-On Code — Python Getter and Setter Methods to Access and Modify the Private Attributes
November 29, 2024 - Setter: Used to modify the value of a private or protected attribute while applying validation or other logic. Let’s take an example of a class that represents a Bank Account with private attributes for account balance.
🌐
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 - In this example, __price is a private variable of the Product class. Encapsulation: They hide the internal state of an object from outside interference. Security: Prevents external entities from modifying the state in an uncontrolled manner. Maintenance: Makes it easier to change the attribute implementation without affecting external users. ... Python provides a property function that makes the implementation of getters and setters ...
🌐
TutorialsPoint
tutorialspoint.com › What-are-Getters-Setters-methods-for-Python-Class
Getters and Setters Methods for Python Class
May 29, 2025 - class Sum: def __init__(self, var1, var2): self._var1 = var1 self._var2 = var2 print("Sum:", self._var1 + self._var2) # Getter for var1 def get_var1(self): return self._var1 # Setter for var1 def set_var1(self, value): self._var1 = value # Properly update the attribute # Create object obj1 = Sum(15, 78) # Get value using getter print("Getter method:", obj1.get_var1()) # Set new value using setter obj1.set_var1(100) # Verify the change print("Updated value after setter:", obj1.get_var1()) ... In Python, property() is a built-in function that allows you to create properties with getter and setter behavior.
🌐
LinkedIn
linkedin.com › pulse › getter-setter-python-vinayak-sharma
Getter and Setter in Python
December 26, 2022 - class Student(object): def __init__(self, name: str) -> None: self.name: str = name self.__marks: int = 0 @property def marks(self): """ getter method Get Method in python """ return self.name + " got " + str(self.__marks) @marks.setter def marks(self, marks: int): """ setter method Set Method in python """ self.__marks = marks @marks.deleter def marks(self): """ Del Method """ self.__marks = 0 return 1 def __str__(self) -> str: return "student name is " + self.name s = Student("vinayak") print(s) s.marks = 10 marks_s_got = s.marks print(marks_s_got) del s.marks print(s.marks)
🌐
Eli Bendersky
eli.thegreenplace.net › 2009 › 02 › 06 › getters-and-setters-in-python
Getters and setters in Python - Eli Bendersky's website
This is why in C++/Java, people use getters and setters from the start. But in languages like Python it's unnecessary! You can just begin with a plain attribute, letting clients access it. If, at some point, a need will arise to hide the attribute from direct access, no problem, just use the property function. The canonical example is degrees and radians.