Using 'property' in evolving code

Chris Mellon arkanes at gmail.com
Mon Dec 17 12:55:53 EST 2007


On Dec 17, 2007 11:48 AM, Steven Clark <steven.p.clark at gmail.com> wrote:
> Hi all-
> I was reading http://dirtsimple.org/2004/12/python-is-not-java.html, in
> particular the part about "getters and setters are evil":
>  "In Java, you have to use getters and setters because using public fields
> gives you no opportunity to go back and change your mind later to using
> getters and setters. So in Java, you might as well get the chore out of the
> way up front. In Python, this is silly, because you can start with a normal
> attribute and change your mind at any time, without affecting any clients of
> the class. So, don't write getters and setters."
>
> I understand the idea behind this, but how does this transition work in
> actuality?
> Lets say I define class Foo initially as...
>
> class Foo(object):
>     def __init__(self, x):
>         self.x = x
>
>     def get_sqrt(self):
>         return sqrt(self.x)
>
> Fine. I can read from x, and write to x:
> def test():
>     f = Foo(9)
>     print 'sqrt of', f.x, 'is', f.get_sqrt()
>      f.x = 16
>     print 'sqrt of', f.x, 'is', f.get_sqrt()
>
> Let's say later on I decide that f.get_sqrt will be called far more often
> than f.x is changed, and that it therefore makes sense to store the actual
> sqrt in the class, rather than calling math.sqrt each time f.get_sqrt is
> called. So I rewrite Foo:
>
> class Foo(object):
>     def __init__(self, x):
>         self._x = x
>         self._my_root = sqrt(x)
>
>     def _set_x(self, x):
>         self._x = x
>         self._my_root = sqrt(x)
>
>     def get_sqrt(self):
>         return self._my_root
>
>     x = property(lambda self: self._x, _set_x)
>
> External to the class, everything behaves as before, except with the benefit
> of not having to wait for slow sqrt each time. self.x is now a property
> rather than an attribute. Internal to the class, I have to search & replace
> all old occurences of "self.x" with "self._x"? Otherwise there is a
> collision between f.x the attribute and f.x the property?
>

You only need to update uses of the attribute that *need* the raw
attribute, and not the property. Quite often these are just your (new)
getters and setters, as you see. There is no "collision" - properties
and (raw) attributes are accessed the same way. Any use of f.x will go
through the property.



More information about the Python-list mailing list