Reputation: 15615
If you have a value that doesn't change, is there anything wrong with defining it just with @property and return the value as follows:
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def pi(self):
return 3.14
def area(self):
return self.pi * self.radius
Since PI shouldn't change and the value is static, is there anything wrong defining it with @property as shown above?
What I usually see is the following:
class Circle:
def __init__(self, radius):
self.radius = radius
self.pi = 3.14
def area(self):
return self.pi * self.radius
Upvotes: 0
Views: 83
Reputation: 2965
If you want to be sure to make it immutable, you can define the attribute refuse to be set.
class Circle:
_pi = 3.14
def __init__(self, radius):
self.radius = radius
@property
def pi(self):
return _pi
@pi.setter
def pi(self, value):
pass
...
The pi is immutable.
c = Circle(1)
c.pi = 5 # The intent is to make it change
print c.pi # Output: 3.14, it still keeps origin.
Upvotes: 0
Reputation: 2392
The problem with using a property is this:
>>> d = Circle()
>>> d.pi
3.14
>>> d.pi = 3
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
d.pi = 3
AttributeError: can't set attribute
>>> Circle.pi = 3
>>> d.pi
3
You may be able to get around this with a metaclass:
class NoSet(type):
def __setattr__(self, name, value):
if name == 'pi':
raise Exception("Can't assign")
else:
super(NoSet, self).__setattr__(name, value)
class Circle(object):
__metaclass__ = NoSet
@property
def pi(self):
return 3.14
>>> d = Circle()
>>> d.pi
3.14
>>> d.pi = 3
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
d.pi = 3
AttributeError: can't set attribute
>>> Circle.pi = 3
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
Circle.pi = 3
File "<pyshell#43>", line 4, in __setattr__
raise Exception("Can't assign")
Exception: Can't assign
For usage in Python 3 change the class definition to class Circle(object, metaclass=NoSet):
.
Disclaimer: I just tried this a moment ago and it seemed to work. I can't make any promises as I have not had much experience with metaclasses. I personally wouldn't do this, if only because there might be a legitimate reason for someone to change the value - if they needed more precision, for example.
Upvotes: 0
Reputation: 1394
Python programmers I know generally avoid accessor functions, unless they're actually performing computation. In this case you'd be better off with making the variable a member of the class:
class Circle:
pi = 3.14
def __init__(self, radius):
self.radius = radius
# ...
Upvotes: 2