I am generally confused about the difference between a "property" and an "attribute", and can't find a great resource to concisely detail the differences.
8 Answers
Properties are a special kind of attribute. Basically, when Python encounters the following code:
spam = SomeObject()
print(spam.eggs)
it looks up eggs
in spam
, and then examines eggs
to see if it has a __get__
, __set__
, or __delete__
method — if it does, it's a property. If it is a property, instead of just returning the eggs
object (as it would for any other attribute) it will call the __get__
method (since we were doing lookup) and return whatever that method returns.
More information about Python's data model and descriptors.

- 84,998
- 9
- 154
- 353

- 63,992
- 20
- 159
- 237
-
It sounds like properties involve additional processing to access the target value...do you know how significant / much slower it is? – martineau Jun 25 '18 at 16:14
-
1@martineau: Well, there's one extra function call, but most likely the extra work and time will depend on how much the property is doing (general advice: do /not/ use properties to hide I/O). – Ethan Furman Jun 25 '18 at 23:37
With a property you have complete control on its getter, setter and deleter methods, which you don't have (if not using caveats) with an attribute.
class A(object):
_x = 0
'''A._x is an attribute'''
@property
def x(self):
'''
A.x is a property
This is the getter method
'''
return self._x
@x.setter
def x(self, value):
"""
This is the setter method
where I can check it's not assigned a value < 0
"""
if value < 0:
raise ValueError("Must be >= 0")
self._x = value
>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
File "ex.py", line 15, in <module>
a.x = -1
File "ex.py", line 9, in x
raise ValueError("Must be >= 0")
ValueError: Must be >= 0

- 11,500
- 2
- 40
- 63
-
This ("complete control") can be done with "non-property" attributes as well though, just without such simple decorators. – Sep 10 '11 at 21:41
-
25I like that this answer provides a realistic and useful example. I feel that too many answers on this site needlessly explain how things work on the back-end without clarifying how the user should interact with them. If one doesn't understand why/when to use some functionality, there is no point knowing how it operates behind the scenes. – Tom Dec 03 '15 at 18:44
-
This answer violate the "Zen of Python - There should be one -- and preferably only one -- obvious way to do it". There are 2 ways to set x value. – Tin Luu Aug 22 '17 at 02:51
-
1@TinLuu - There is only one way to set the value of x. There is also only one way to set the value of _x. The fact that they are the same thing is an implementation detail. The wise user of this class does not use _x. – lit Sep 20 '17 at 20:48
-
@lit: considering _x, a.x=1 or a._x=1 both change value of _x, isn't that multiple way to change value of _x? – Tin Luu Sep 26 '17 at 09:43
-
2@TinLuu - I think we are both saying the same thing from opposite ends of the perspective. The user of the class should only see `x`. One way. If the user of the class finds out about _x, they use it at their own risk. – lit Sep 26 '17 at 13:34
-
@TinLuu, considering _x, a.x=-1 or a._x=-1 they behave differently and that's the point in having getters and setters. Otherwise just use attributes. – neurino Sep 28 '17 at 19:13
In general speaking terms a property and an attribute are the same thing. However, there is a property decorator in Python which provides getter/setter access to an attribute (or other data).
class MyObject(object):
# This is a normal attribute
foo = 1
@property
def bar(self):
return self.foo
@bar.setter
def bar(self, value):
self.foo = value
obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo

- 2,886
- 21
- 20
-
1could you please also mention the expected outcome of this code? – QuestionEverything Jul 29 '17 at 18:30
-
2
The property allows you to get and set values like you would normal attributes, but underneath there is a method being called translating it into a getter and setter for you. It's really just a convenience to cut down on the boilerplate of calling getters and setters.
Lets say for example, you had a class that held some x and y coordinates for something you needed. To set them you might want to do something like:
myObj.x = 5
myObj.y = 10
That is much easier to look at and think about than writing:
myObj.setX(5)
myObj.setY(10)
The problem is, what if one day your class changes such that you need to offset your x and y by some value? Now you would need to go in and change your class definition and all of the code that calls it, which could be really time consuming and error prone. The property allows you to use the former syntax while giving you the flexibility of change of the latter.
In Python, you can define getters, setters, and delete methods with the property function. If you just want the read property, there is also a @property decorator you can add above your method.

- 1,299
- 1
- 10
- 18
I learnt 2 differences from site of Bernd Klein, in summary:
1. A property is a more convenient way to achieve data encapsulation
For example, let's say you have a public attribute length
. Later on, your project requires you to encapsulate it, i.e. to change it to private and provide a getter and setter => you have to change the the code you wrote before:
# Old code
obj1.length = obj1.length + obj2.length
# New code (using private attributes and getter and setter)
obj1.set_length(obj1.get_length() + obj2.get_length()) # => this is ugly
If you use @property
and @length.setter
=> you don't need to change that old code.
2. A property can encapsulate multiple attributes
class Person:
def __init__(self, name, physic_health, mental_health):
self.name = name
self.__physic_health = physic_health
self.__mental_health = mental_health
@property
def condition(self):
health = self.__physic_health + self.__mental_health
if(health < 5.0):
return "I feel bad!"
elif health < 8.0:
return "I am ok!"
else:
return "Great!"
In this example, __physic_health
and __mental_health
are private and cannot be accessed directly from outside.
There is also one not obvious difference that i use to cache or refresh data , often we have a function connected to class attribute. For instance i need to read file once and keep content assigned to the attribute so the value is cached:
class Misc():
def __init__(self):
self.test = self.test_func()
def test_func(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Output:
func running
func value
func value
We accessed the attribute twice but our function was fired only once. Changing the above example to use property will cause attribute's value refresh each time you access it:
class Misc():
@property
def test(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
Output:
func running
func value
func running
func value

- 249
- 2
- 6
I like to think that, if you want to set a restriction for an attribute, use a property.
Although all attributes are public, generally programmers differentiate public and private attributes with an underscore(_
). Consider the following class,
class A:
def __init__(self):
self.b = 3 # To show public
self._c = 4 # To show private
Here, b
attribute is intended to be accessed from outside class A. But, readers of this class might wonder, can b
attribute be set from outside class A
?
If we intend to not set b
from outside, we can show this intention with @property
.
class A:
def __init__(self):
self._c = 4 # To show private
@property
def b(self):
return 3
Now, b
can't be set.
a = A()
print(a.b) # prints 3
a.b = 7 # Raises AttributeError
Or, if you wish to set only certain values,
class A:
@property
def b(self):
return self._b
@b.setter
def b(self, val):
if val < 0:
raise ValueError("b can't be negative")
self._b = val
a = A()
a.b = 6 # OK
a.b = -5 # Raises ValueError

- 360
- 2
- 8
Attribute is actually at the object.
Property is propagated by proxy. (Its value may be calculated on the fly.)
See also

- 13
- 3
-
1As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 08 '23 at 11:13