Divorce property objects from attribute access dependency?

Gustavo Cordova gcordova at hebmex.com
Mon Jun 17 13:49:06 EDT 2002


> 
>  >>> class C(object):
>  ...     def __init__(self,v):
>  ...         self._v = v
>  ...     def get_v(self): return self._v
>  ...     def set_v(self,v): self._v = v
>  ...     v=property(get_v,set_v)
>  ...     vlist = [v,v]
>  ...
>  >>> c=C('something')
>  >>> c.v
>  'something'
>  >>> c.v='other'
>  >>> c.v
>  'other'
>  >>> c.vlist
>  [<property object at 0x0082D4A0>, <property object at 0x0082D4A0>]
>  >>> c.vlist[0]
>  <property object at 0x0082D4A0>
> 
> Why not trigger get_v() in these accesses too, and have 
> single mechanism to suppress it instead of a single
> mechanism to effect it?
>

You mean that you don't recognize the difference between
evaluating "c.v" and "c.vlist"?

Well, for one:

"c.v" is evaluated at runtime, and it's recognized as
an instance's access to a class' property attribute,
so all the background magic happens (which is what
you expected). Just a note: get_v and set_v are
methods, which take "self", and all that. Ok.

On the other hand, "vlist" is created at compile
time, and it's a list, not a property attribute;
it's only a list with two objects. When you're
evaluating "c.vlist", the items in the list are not
in the correct context to be evaluated as property
attributes, so the background magic does not happen.
For one, there is no "self" to pass to the methods
get_v and set_v; another, they're "property attributes",
not "magical list items". :-)
 
> ISTM kind of a hack to rig access via instance attribute as a 
> mechanism for controlling referenced-object behavior (this is
> my impression, I haven't checked code ;-). IMO default behavior
> of an object in lhs or rhs context should not depend on how a
> reference to it was acquired and dereferenced.
> 
> (Obviously, if property objects always acted as they now do 
> through instance attribute access, "vlist=[v,v]" in this
> example would have to have some kind of access override like
> "vlist = [obj(v),obj(v)]", or else it would generate 
> ['something','something'] right there. Using obj(p) a property
> object could be passed around without evaluation and the
> potential side effects thereof).
> 

A property object *can* be passed around without side effects,
it's only when accesed as an attribute of an instance of a
class which defines them, that the expected behaviour
triggers.

For example, try this:

>>> class klass(object): pass
...
>>> ob = klass()
>>> ob._blah = 10
>>> def _get_blah(self): return self._blah
>>> def _set_blah(self, b): self._blah = b
>>> ob.blah = property(_get_blah, _set_blah)

What behaviour do you expect from this? Give it a try. :-)

> BTW, it would be nice to be able to define a property at 
> global module scope also, and perhaps this would tie in nicely.
> 
> Just musing ;-) Thoughts? Am I missing a big gotcha?
> One thing is that it will effectively make possible a ()-less 
> function call, which will upset some people ;-)

You can do that without properties:

>>> class Caller:
...    def __init__(self, func, *args, **kw):
...       self.func, self.args, self.kw = func, args, kw
...    def __str__(self): return self.func(*args, **kw)
...    __repr__ = __str__
...
>>> def PrintTen(): print 10
...
>>> ten = Caller(PrintTen)
>>> ten
10

Another thing, you *can* create "magical list items"
with this class; since __repr__ is also defined,
then when the list which contains them is rendered,
the __repr__ method of the items is called. Neat. :-)

I Know, it's a simple-minded example, but you know
what I mean. You can use this Caller class to execute
a function when you type the name of the object that's
related to the function.

Good luck :-)

-gustavo

> 
> Regards,
> Bengt Richter
> 





More information about the Python-list mailing list