Hello, There are a lot of Python mailing lists. I hope this is an appropriate one for a question on properties.
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. 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). As a user interface designer, I respect how this may prevent the programmer's deluge of unimportant information. I also value the ease of refactoring, which is a frequent task in my prototypes. 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. PythonWin 2.4.3 - Enthought Edition 1.0.0 (#69, Aug 2 2006, 12:09:59) [MSC v.1310 32 bit (Intel)] on win32. Portions Copyright 1994-2004 Mark Hammond ([EMAIL PROTECTED]) - see 'Help/About PythonWin' for further copyright information. >>> class a_class: ... def __init__( self ): self.__p = None ... def __set_p( self, new_p ): self.__p = new_p ... def reset( self ): self.__p = None ... p = property( lambda self: self.__p, __set_p ) ... >>> a = a_class() >>> a.p >>> a.p = 1 >>> a.p 1 >>> a.reset() >>> a.p 1 Although the underlying value was reset, the property was not reset! Instead, if the property is edited, then all is fine. >>> class a_class: ... def __init__( self ): self.__p = None ... def __set_p( self, new_p ): self.__p = new_p ... def reset( self ): self.p = None # Property, not the private member ... p = property( lambda self: self.__p, __set_p ) ... >>> a = a_class() >>> a.p >>> a.p = 1 >>> a.reset() >>> a.p 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? By the way, I thought maybe that a variable outside of an __init__ method would be static, 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__ ... def __set_p( self, new_p ): self.__p = new_p ... def reset( self ): self.p = None ... p = property( lambda self: self.__p, __set_p ) ... >>> a = a_class() >>> a.p >>> a.p = 1 >>> a.reset() >>> a.p >>> 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. Again, the interface is cleaner. But does this cause an error for derived classes that would use the private data member? Without the __init__ method, is the derived class' __p equal to the base class' __p? I thought maybe the class was being referenced instead of the instance, but a second object had a different value. >>> b = a_class() >>> b.p >>> b.p = 2 >>> b.p 2 >>> b.reset() >>> a.p >>> a.p = 1 >>> a.p 1 >>> b.p >>> b.p = 2 >>> b.reset() >>> a.p 1 >>> b.p >>> Also properties don't show up in the dictionary if no assignment has been made, but once a property's assignment has been called, the property appears. An example follows: >>> import pprint >>> pprint.pprint( a.__dict__ ) {'p': 1} >>> pprint.pprint( b.__dict__ ) {'p': None} >>> c = a_class() >>> pprint.pprint( c.__dict__ ) {} >>> c.p >>> pprint.pprint( c.__dict__ ) {} Is that dictionary population behavior for detecting an uninitialized property? Thanks for your help. When my feet are properly wet, I look forward to contributing to the community. -- Ethan Kennerly -- http://mail.python.org/mailman/listinfo/python-list