What's the difference between @property and setting in __init __ ()?
Couldn't get a direct response from other threads on this:
In Python, the main difference between using
class Foo(object):
def __init__(self, x):
self.x = x
and
class Foo(object):
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
Apparently, using @property this way is read-only x .. but maybe someone has a better answer? Thanks / Fred
source to share
In your example, yes, it allows you to have read-only attributes. Also, properties can allow you to have more attributes than you actually do. Consider a circle with .radius
and .area
. Area can be calculated based on radius, not storage as
import math
class Circle(object):
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * (self.radius ** 2)
source to share
The decorator implementation property
uses the descriptor protocol , which is how we encapsulate data in Python OOP. Descriptor:
In general, the handle - an attribute of an object with a binding behavior ", one whose attribute access has been overridden by methods in the descriptor protocol, these methods are.
__get__()
,__set__()
And__delete__()
if any of these methods defined for the object, it is called a descriptor..
Typically, other OOP languages use getters and setters. You will often see people show up, like Java, writing a Python class like this:
class A(object):
def __init__(self, x, y):
self._x = x
self._y = y
def getX(self):
return self._x
def getY(self):
return self._y
def setX(self, x):
self._x = x
def setY(self, y):
self._y = y
def some_method_that_uses_attributes(self):
return self.getX() + self.getY()
This is not how you would do anything in Python. The Getters and Setters point should provide data encapsulation. We will encapsulate access to the data attribute by wrapping it in a getter and setter. Then if we ever want to add something, say make sure it's x
never set to a value below 10 (as a contrived example), we just change the way setX
and we don't need to change the rest of our code. However, in Python, we will write the above class like this:
class A(object):
def __init__(self, x, y):
self.x = x
self.y = y
def some_method_that_uses_attributes(self):
return self.x + self.y
A person who comes from Java may be horrified: "You are not encapsulating your class correctly! This will be a maintenance nightmare!"
No, because we have descriptors / properties:
class A(object):
def __init__(self, x, y):
self._x = x
self.y = y
@property
def x(self):
return self._x
@x.setter
def x(self, val):
if val > 10:
self._x = val
else:
raise ValueError("x must be greater than 10")
def some_method_that_uses_attributes(self):
return self.x + self.y
And now we don't have to refract every method we use self.x
, for example some_method_that_uses_attributes
. This is good, because it allows us not to write a bunch of boilerplate code, and the implementation of descriptors is relatively straightforward when we need it. Moreover, it makes our code nice and nice, without self.get_this()
and self.set_that(3)
throughout the code, and much more readable self.this
andself.that = 3
source to share
Please post this SO post on Python properties - this refers to getters / setters, but the answers break down a lot more about them, and I believe everything you want to know is in there: Python @property vs getters and setters
source to share