Using properties

bruno modulix onurb at xiludom.gro
Wed May 25 11:41:20 EDT 2005


tkpmep at hotmail.com wrote:
> I have a class with a name attribute, which I want to modify using
> property.The following code works just fine:
> 
> class Portfolio(object):
> 
>     def __init__( self, name="Port1"):
>         self.name=name

This may not do what you think it does (see below)

> 
>     def getname(self):
>         return self._name
>     def setname(self,newname="Port2"):
>         self._name=newname
> 
>     name=property(getname,setname,None,None)
> 
> However, it no longer works if I modify getname and setname to
> 
>     def getname(self):
>         return self.name
> 
>     def setname(self,newname="Port2"):

what's the use of putting a default value here ?

>         self.name=newname

How could this work, since self.name is now a property object that calls
 on setname() and getname() ?

> Why is it so critical to have getname and setname modify _name and not
> name? 

because 'name' is how you named your property...

> The constructor does not make name a private attribute, 

Note that there is in fact no notion of private/public in Python (I mean
: in the language). The underscore stuff is nothing more than a convention.

Now you don't seem to understand what happens when __init__ is called.
Try this:

8<------------------------------------------------
class Portfolio(object):

    def __init__( self, name="Port1"):
        self.name=name
        print "self._name is %s" % self._name
        print "self.__class__.name is %s" % self.__class__.name

    def _getname(self):
        print "in getname"
        return self._name

    def _setname(self, newname):
        print "in setname"
        try:
            print "self._name is %s" % self._name
        except AttributeError, e:
            print "got AttributeError %s" % e
            print "when trying to access self._name"
        self._name=newname

    name=property(fget=_getname, fset=_setname)
    print "in Portfolio class definition : name is %s" % name

p = Portfolio()
8<------------------------------------------------

As you can see, the 'name=property(...)' statement at the end of your
class definition is executed when the class definition is first eval'd
(this is when the code is loaded in the interpreter). So when __init__
is called, the statement 'self.name = name' does not create an instance
variable 'name', but calls the existing property, which in turn creates
the instance variable '_name'.

> so why do
> getname and setname have to treat it as such?

>From a technical POV, we don't care if the attribute accessed by a
property is 'private' or whatever. The only thing is that it can't have
the same name as the property...

>From a conceptual POV, it makes no sense (well, IMHO) to use a property
for a 'public' (by convention...) attribute. Either you want a property
(think : a computed attribute) and then you hide the implementation
details, or you're ok with a plain old 'public' attribute and then you
don't use a property.

BTW, this is also true of the setter and getter used by the property:
they are implementation details, and as such should not be exposed as
part of the interface.

HTH
-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list