newb question about @property

Steve D'Aprano steve+python at pearwood.info
Mon Oct 2 20:00:24 EDT 2017


On Tue, 3 Oct 2017 06:32 am, Bill wrote:
> Steve D'Aprano wrote:
>> Circle didn't use any setters, but I could have let you set the
>> diameter, which in
>> turn would set the radius:
>>>> circle.radius = 2
>> assert circle.diameter == 4
>> circle.diameter == 2 # requires a setter
>> assert circle.radius == 1
>>>> Getting that to work is left as an exercise :-)
>>> It WAS a good exercise!! I was concerned about "infinite recursion"
> between my two property setters.. Thanks! Next? :)
>> Bill
>>> import math
>>> class Circle(object):
> """ Define a circle class with radius and diameter"""
> def __init__(self, radius):
> self.radius = radius
> self.diameter =2*radius

There's no need to set the radius and the diameter, as one is completely derived
from the other and the transformation is cheap enough to perform on the fly as
needed.
Consider what happens if, due to a bug or an accident, you end up with a Circle
instance that says the radius is 5 and the diameter is 20. They can't *both* be
right, and you will get inconsistent results depending on whether your other
methods happen to use the diameter or the radius.
Instead, we should steal the Single Source Of Truth principle from informations
systems theory:
https://en.wikipedia.org/wiki/Single_source_of_truth
https://en.wikipedia.org/wiki/Single_version_of_the_truth
There are valid cases for violating this principle in object design, e.g. caches
are technically a violation of SSOT but an acceptable one.
With that in mind, your class simplifies to:
class Circle(object):
 """ Define a circle class with radius and diameter"""
 def __init__(self, radius):
 self.radius = radius
 @property
 def radius(self):
 return self._radius
 @radius.setter
 def radius(self, value):
 self._radius = value
 @property
 def diameter(self):
 return 2*self._radius
 @diameter.setter
 def diameter(self, value):
 self._radius = value/2
 @property
 def area(self):
 return math.pi*self.radius**2
 @property
 def circumference(self):
 return math.pi*self.diameter
-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.


More information about the Python-list mailing list

AltStyle によって変換されたページ (->オリジナル) /