How to write Smart Python programs?

Ben Finney bignose+hates-spam at benfinney.id.au
Wed Oct 11 12:23:44 CEST 2006


Antoine De Groote <antoine at vo.lu> writes:

> Ok, the first Google result 
> (http://dirtsimple.org/2004/12/python-is-not-java.html) says this somewhere:
>
> "Getters and setters are evil. Evil, evil, I say! Python objects are
> not Java beans. Do not write getters and setters. This is what the
> 'property' built-in is for. And do not take that to mean that you
> should write getters and setters, and then wrap them in
> 'property'. (1) That means that until you prove that you need
> anything more than a simple attribute access, don't write getters
> and setters. They are a waste of CPU time, but more important, they
> are a waste of programmer time. Not just for the people writing the
> code and tests, but for the people who have to read and understand
> them as well. [...]"
>
> What exactly is meant by (1)? The python library reference includes
> this as an example:
>
> class C(object):
>      def __init__(self): self.__x = None
>      def getx(self): return self._x
>      def setx(self, value): self._x = value
>      def delx(self): del self._x
>      x = property(getx, setx, delx, "I'm the 'x' property.")
>
> To me this seems contradictory. Why would one not want to do
> something that is included in the documentation? Or am I just
> confused? Does anybody have an idea how to put me in the right
> direction?

Note that, to a user of that class, the fact that it's implemented as
a property is opaque. Thus, changing an attribute from a simple value
object, to a property, can be done as and when needed, without
changing any of the code that uses that class.

So, it's best to always code plain public attributes without getters
and setters in the first instance:

    >>> class Foo(object):
    ...     def __init__(self):
    ...         self.menu = "spam"
    ...

    >>> foo = Foo()
    >>> foo.menu
    'spam'
    >>> foo.menu = "sausage"
    >>> foo.menu
    'sausage'

Because later, when one wants to refactor the implementation of that
attribute without changing the interface, only the implementation
needs to change:

    >>> class Foo(object):
    ...     def __init__(self):
    ...         self._menu = ["spam", "eggs", "beans"]
    ...         self.current_item = 0
    ...     def _get_menu(self):
    ...         return self._menu[self.current_item]
    ...     def _set_menu(self, value):
    ...         self._menu[self.current_item] = value
    ...     menu = property(_get_menu, _set_menu)
    ...

And the code that uses that attribute can remain the same:

    >>> foo = Foo()
    >>> foo.menu
    'spam'
    >>> foo.menu = "sausage"
    >>> foo.menu
    'sausage'

Thus, coding getters and setters without a demonstrated need to do so
in a particular case is a waste of effort and an increase in
complexity, with no benefit.

> I'm not done with 'How To Ask Questions The Smart Way' yet, so
> please forgive any violations.

Your awareness of that document, and your attempt to follow it
sincerely, is much more important.

-- 
 \      "He that would make his own liberty secure must guard even his |
  `\                          enemy from oppression."  -- Thomas Paine |
_o__)                                                                  |
Ben Finney




More information about the Python-list mailing list