472,958 Members | 2,599 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 software developers and data experts.

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

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 (mh******@skippinet.com.au) - 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
Jun 19 '07 #1
8 1594
Ethan Kennerly <ke******@finegamedesign.comwrote:
...
There are a lot of Python mailing lists. I hope this is an appropriate one
for a question on properties.
yep, it's a fine one.
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.
You're interpreting wrongly the symptoms you're observing.
>class a_class:
This is ALL of the problem: you're using a legacy (old-style) class, and
properties (particularly setters) don't work right on its instances (and
cannot, for backwards compatibility: legacy classes exist exclusively to
keep backwards compatibility with Python code written many, many years
ago and should be avoided in new code).

Change that one line to

class a_class(object):

and everything else should be fine. If you want, I can try to explain
the why's and wherefore's of the problem, but to understand it requires
deeper knowledge of Python than you'll need for just about any practical
use of it: just retain the tidbit "NEVER use oldstyle classes" and you
won't need to understand WHY you shouldn't use them:-).
Alex
Jun 19 '07 #2

Alex Martelli wrote:
>
>>>>class a_class:

This is ALL of the problem: you're using a legacy (old-style) class, and
properties (particularly setters) don't work right on its instances (and
cannot, for backwards compatibility: legacy classes exist exclusively to
keep backwards compatibility with Python code written many, many years
ago and should be avoided in new code).

Change that one line to

class a_class(object):

and everything else should be fine. If you want, I can try to explain
the why's and wherefore's of the problem, but to understand it requires
deeper knowledge of Python than you'll need for just about any practical
use of it: just retain the tidbit "NEVER use oldstyle classes" and you
won't need to understand WHY you shouldn't use them:-).
Can you elaborate (or just point me to a good doc) on what you mean by an "old style" class versus the new style? I learned Python (well, am still learning) from an older book, and I just want to make sure that I'm using the preferred method.

Thanks,

-Jay
Jun 19 '07 #3

Jay Loden wrote:
Can you elaborate (or just point me to a good doc) on what
you mean by an "old style" class versus the new style? I
learned Python (well, am still learning) from an older book,
and I just want to make sure that I'm using the preferred method.
Answering my own question, I know, but Google and the right keywords is a wonderful thing. In case anyone else is interested:

http://www.python.org/doc/newstyle.html

-Jay
Jun 19 '07 #4
"Ethan Kennerly" <ke******@finegamedesign.comwrites:
I really like properties for readonly attributes,
Python doesn't have "readonly attributes", and to attempt to use
properties for that purpose will only lead to confusion.
and their ability to make the interface more elegant, by hiding
uninteresting methods (like dumb get/set accessors).
The best solution to this is not to create get/set accessors at
all. Just define a simple data attribute, name the attribute
logically, and use it normally. When the interface demands something
other than a plain attribute, *then* consider changing it to a
property; but prefer a plain data attribute in the usual case.
>class a_class:
Define your classes as inheriting from 'object', or some other type in
the Python type hierarchy, and properties will work as expected.

class a_class(object):
# foo

--
\ "When I get real bored, I like to drive downtown and get a |
`\ great parking spot, then sit in my car and count how many |
_o__) people ask me if I'm leaving." -- Steven Wright |
Ben Finney
Jun 19 '07 #5
On Tue, 19 Jun 2007 18:54:41 +1000, Ben Finney wrote:
"Ethan Kennerly" <ke******@finegamedesign.comwrites:
>I really like properties for readonly attributes,

Python doesn't have "readonly attributes", and to attempt to use
properties for that purpose will only lead to confusion.

class Parrot(object):
def _plumage(self):
return "Beautiful red plumage"
plumage = property(_plumage)

>>parrot = Parrot()
parrot.plumage
'Beautiful red plumage'
>>parrot.plumage = "Ragged grey feathers"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

It walks like a read-only attribute, it squawks like a read-only
attribute, but since Python doesn't have read-only attributes, Ben must be
right: using properties to implement read-only attributes will only lead
to confusion.

*wink*
--
Steven.

Jun 19 '07 #6
Ben Finney <bi****************@benfinney.id.auwrote:
"Ethan Kennerly" <ke******@finegamedesign.comwrites:
I really like properties for readonly attributes,

Python doesn't have "readonly attributes",
Many Python types do, e.g.:
>>def f(): pass
....
>>def g(): pass
....
>>f.func_name = 'zap'
f.func_code = g.func_code
f
<function zap at 0x66070>
>>f.func_code
<code object g at 0x55458, file "<stdin>", line 1>
>>f.func_closure = g.func_closure
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: readonly attribute

i.e., you can reassign some of f's attributes (such as its name and
code) but others (such as its closure) are readonly (as the TypeError's
message says) so you cannot reassign those.

It makes just as much sense for user-coded types (aka classes) to have
some r/w attributes and others that are readonly, as it does for builtin
types -- and properties are often the simplest way to accomplish that.
and to attempt to use
properties for that purpose will only lead to confusion.
I disagree -- a property is a great way to implement readonly
attributes, as long as you're using a new-style class of course.
class Rectangle(object):

def __init__(self, w, h):
self.w = w
self.h = h

area = property(lambda self: self.w * self.h)

No confusion here -- given a Rectangle instance r, you can both read and
write (reassign) r.w and r.h, but r.area is readonly (can't be set):
>>r = Rectangle(12, 34)
r.area
408
>>r.h = 10
r.area
120
>>r.area = 144
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
Alex
Jun 19 '07 #7
Ben Finney a écrit :
"Ethan Kennerly" <ke******@finegamedesign.comwrites:
>I really like properties for readonly attributes,

Python doesn't have "readonly attributes",
Err... Ever tried to set a class mro ?-)
and to attempt to use
properties for that purpose will only lead to confusion.
read-only attributes actually are one of the common use-case for properties.

Jun 20 '07 #8
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...
Jun 20 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: YellowDog | last post by:
I want to use a property without a private data member. This is supposed to be legal, except that I get an Stack Overflow Exception when I implicity use the set method. Here's the code: Option...
1
by: Ondrej Sevecek | last post by:
Hello, I have a general problem in mind. Imagine, you have a private member and its associated property: private int member; public int Member { get return member; set {a better code...
3
by: nicver | last post by:
I am fixing a client's Web site and for some reason an ASP class does not want to use the variables it retrieves when it initialiases. This is an excerpt of the class and it is enough to show...
20
by: Scott Simons | last post by:
Why doesn't the compiler throw an error on a block of code like this: public string Email { get { return Email; } }
6
by: David Whitchurch-Bennett | last post by:
Hi There, I have created a very simple web user control, containing only a combo box. I have created a class which contains some private object variables, for example... Private _anObject as...
2
by: Jon Paal | last post by:
In a 2.0 vb code class, I have a private property and a shared public function The property value has already been passed into the class, now I am trying to use a public finction which also needs...
8
by: David Veeneman | last post by:
Should a member variable be passed to a private method in the same class as a method argument, or should the method simply call the member variable? For years, I have passed member variables to...
3
by: =?Utf-8?B?Ulc=?= | last post by:
I constructed a new Class with some private members. I would like an event to be raised on the moment the value of one of those private members is changed. How do I define an event for that...
11
by: Yarco | last post by:
For example: <?php class Test { private $name = 'yarco'; } $p = new ReflectionPropery('Test', 'name'); print $p->getValue();
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.