Newbie: Why doesn't this work
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Mon Dec 31 12:36:45 EST 2007
En Mon, 31 Dec 2007 14:56:02 -0200, <ct60 at aol.com> escribi�:
> Hi Python Community:
>
> Despite my new-ness to Python I have alreadhy been able to do some (I
> think) amazing things. It is a truly elegant and smart language.
>
> Yet, I can not seem to get a handle on something simple.
>
> I would like to make a class which has private varaiables fName and
> lName. It should have a property "name" which can get or set a name.
> Something like as follows:
>
> class Person:
> def __init__(self, fName="", lName=""):
> self.__fName = fName
> self.__lName = lName
>
> def __getattr__(self, attr):
> if attr == "name":
> return self.__fName + " " + self.__lName
>
> def __setattr__(self, attr, value):
> # this assumes that value is a tuple of first and last name
> if attr == "name":
> self.__fName, self.__lName = value
__getattr__ gets called when an attribute lookup fails in the "standard"
places. Your version, when attr is not "name", does nothing - effectively
returning None for *any* other attribute.
You should raise an AttributeError instead: add this line after the if:
raise AttributeError, attr
__setattr__, on the other hand, is called with *any* attempt to set an
attribute. Your version effectively makes Person "read only"; the only
attribute you can set is "name". We could fix that, but there are better
ways. Forget about __getattr__ and __setattr__ and use a property:
class Person(object):
def __init__(self, fName="", lName=""):
self._fName = fName
self._lName = lName
def getName(self):
return "%s %s" % (self._fName, self._lName)
def setName(self, value):
self._fName, self._lName = value
name = property(getName, setName)
Note that:
- I've inherited Person from object. Person is then a "new-style" class,
and only "new-style" classes support properties (and other goodies).
- I've used _fName instead of __fName. The single _ is an indication to
the outside "warning, this is an implementation detail, don't play with
it". (Two underscores are (rarely) used when you want to minimize name
collisions with subclasses.)
- name is now a property, associated to the two functions getName and
setName. It works the way you want:
py> p = Person("John", "Smith")
py> p.name
'John Smith'
py> p.name = "Tom", "Sawyer"
py> p.name
'Tom Sawyer'
Something I don't like in this design, is that you can't assign the
property to itself; p.name = p.name fails because the "set" expects a
tuple and the "get" returns a single string.
--
Gabriel Genellina
More information about the Python-list
mailing list