Does altering a private member decouple the property's value?

Bruno Desthuilliers bruno.42.desthuilliers at wtf.websiteburo.oops.com
Wed Jun 20 08:37:33 EDT 2007


Ethan Kennerly a écrit :
> Hello,
> 
> There are a lot of Python mailing lists.  I hope this is an appropriate one
> for a question on properties.

It is.

> I am relatively inexperienced user of Python.  I came to it to prototype
> concepts for videogames.   Having programmed in C, scripted in Unix shells,
> and scripted in a number of proprietary game scripting languages, I'm
> impressed at how well Python meets my needs.  In almost all respects, it
> does what I've been wishing a language would do.

So welcome onboard !-)

> One example is properties.  I really like properties for readonly
> attributes, and their ability to make the interface more elegant, by hiding
> uninteresting methods (like dumb get/set accessors).

FWIW, since Python has properties, you often just don't need the 
getter/setter pairs. Start with a plain publi attribute, then switch to 
a computed one (using property or a custom descriptor) if and when needed.

> 
> But a gotcha bit me in the behavior of properties that I didn't expect.  
> If another function accesses an underlying data member of a property, then 
> the data member returned by the property is no longer valid.
> 
> Here is a session example.
> 

>>>> class a_class:

oops ! properties don't work properly with old-style classes. Use a 
new-style class instead:

class AClass(object):

> ... 	def __init__( self ):  self.__p = None
> ... 	def __set_p( self, new_p ):  self.__p = new_p

Take care, the name mangling invoked by the '__name' scheme may lead to 
undesired results. This feature should only be used when you want to 
make sure an attribute will not be accidentally used in a derived class. 
The idiomatic way to mark an attribute as "implementation" is a single 
leading underscore, ie: '_name'.

> ... 	def reset( self ):  self.__p = None
> ... 	p = property( lambda self:  self.__p, __set_p )
> ... 

(snip)

> 
> I had wanted to access the private data member in the class to avoid
> side-effects of the set method.
> 
> Can someone show me how to reference the data member underlying a property
> and update the property without calling the property set method?

cf above.

While we're at it, everything in Python being an object - yes, functions 
and methods too -, and there's nothing like a "private" modifier in 
Python. So s/private data member/implementation attribute/ !-)


> By the way, I thought maybe that a variable outside of an __init__ method
> would be static, 

An attribute defined in the class body (ie not in a method) becomes a 
class attribute (shared by all instances).

> but as far as I can tell, it is dynamic.  For example, the
> following class appeared equivalent to the above for tests.   
> 
>>>> class a_class:
> ... 	__p = None     # No __init__

here, you create a class attribute

> ... 	def __set_p( self, new_p ):  self.__p = new_p

And here, you create an instance attribute that will shadow the class 
attribute.

> 
> I preferred not having the __init__ for this example and my prototype,
> because I wasn't doing anything fancy, and it meant one less method that the
> programmer needed to see.

There are other ways to obtain the same result. Like defining the 
__new__ method (the proper constructor).

(snip the rest)

I think you should take some time to learn the Python object model - 
trying to apply C++/Java concepts to Python won't do it. Articles about 
new-style classes and descriptors on python.org should be a good 
starting point.

My 2 cents...



More information about the Python-list mailing list