Reputation: 7924
I am not clear on the use of @property
(advantages and disadvantages). I want to ask for some example using this class built with the help of Martijn.
The data (in text format) always has a x
,y
, and z
to characterize a point (1, 2, and 3 columns of text file). Sometimes I have a "classification
" (4th column) attribute and/or location
(5th column). Depending on how the file is processed (sometimes more attributes).
class Point(object):
__slots__= ("x", "y", "z", "data", "_classification")
def __init__(self, x, y, z):
self.x = float(x)
self.y = float(y)
self.z = float(z)
self.data = [self.x,self.y,self.z]
@property
def classification(self):
return getattr(self, '_classification', None)
@classification.setter
def classification(self, value):
self._classification = value
if value:
self.data = self.data[:3] + [value]
else:
self.data = self.data[:3]
def __len__(self):
return len(self.data)
p = Point(10,20,30)
len(p)
3
p.classification = 1
len(p)
4
p.data
[10.0, 20.0, 30.0, 1]
I wish to add location
when classification
is already set in order to understand the philosophy of using a @property
. I tried with the following code but I don't know if this is pythonic or not:
class Point(object):
__slots__= ("x", "y", "z", "data", "_classification",'_location')
def __init__(self, x, y, z):
self.x = float(x)
self.y = float(y)
self.z = float(z)
self.data = [self.x,self.y,self.z]
@property
def classification(self):
return getattr(self, '_classification', None)
@classification.setter
def classification(self, value):
self._classification = value
if value:
self.data = self.data[:3] + [value]
else:
self.data = self.data[:3]
@property
def location(self):
return getattr(self, '_location', None)
@location.setter
def location(self, value):
self._location = value
if value:
self.data = self.data[:4] + [value]
else:
self.data = self.data[:4]
def __len__(self):
return len(self.data)
p = Point(10,20,30)
p.classification = 1
p.data
[10.0, 20.0, 30.0, 1]
p.location = 100
p.data
[10.0, 20.0, 30.0, 1, 100]
p = Point(10,20,30)
p.location = 100
p.data
[10.0, 20.0, 30.0, 100]
Upvotes: 1
Views: 257
Reputation: 13120
So, your class works, and you're just asking whether it's Pythonic. I'm not an expert, but I will refer you to the Zen of Python:
Explicit is better than implicit.
To me, when you set one property (location, classification) and it ends up silently modifying other attributes, that is implicit, not explicit. I think a better, more cleanly understood use case would be to have something like an assign_location
and/or assign_classification
methods. That way the person using the API can know that he's not just setting an attribute, he's calling a function that has a docstring explaining what it does.
As for what the philosophy of the property is, I'm not sure its inclusion was based so much on philosophy. What the property decorator did was get rid of unsightly things like this:
class Foo:
def __getattr__(self, attr):
if attr == 'location':
...
elif attr == 'classification':
...
One use I'm quite fond of is using properties to make things thread safe. For example:
class Foo(object):
def __init__(self):
self.lock = threading.Lock()
@property
def classification(self):
return self.classification
@classification.setter
def classification(self, value):
with self.lock:
(something else thread-protected)
self.classification = value
Finally, another piece of advice. Unless you know why you're using slots, don't. Unless you know why you need slots, you don't need them.
Upvotes: 3