Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Externally-defined properties?

Reply
Thread Tools

Externally-defined properties?

 
 
Terry Hancock
Guest
Posts: n/a
 
      08-24-2005
Frankly, I was surprised this worked at all, but I tried
creating a property outside of a class (i.e. at the module
level), and it seems to behave as a property:

>>> def get_x(ob):

.... global x
.... return str(x)
....
>>> def set_x(ob, value):

.... global x
.... x = int(value)
....
>>> def del_x(ob):

.... global x
.... del x
....
>>> def x_access():

.... return property(get_x, set_x, del_x, "X defined externally?")
....
>>>
>>> class Accessor(object):

.... s_x = x_access()
.... def __str__(self):
.... print "Accessor has x = %s" % self.s_X
....
>>> a = Accessor()
>>> a.s_x = 3
>>> a.s_x

'3'
>>> dir()

['Accessor', '__builtins__', '__doc__', '__name__', 'a', 'del_x', 'get_x', 'p', 'set_x', 'x', 'x_access']
>>> x

3

(of course in the real example, x will probably be in an
entirely different module, used as a library -- the client code
just calls a function to get a property that is automatically
managed for it).

So far, the only problem I see is that it only works if the
property is assigned to a new-type class attribute (otherwise,
the first assignment simply replaces the property).

I'm thinking of using this to tie a property of a class to an
external data source (a joystick axis, in fact -- or at least
its last-polled value).

There is a more convential way to do this, of course -- I could
just use a "get_value" function, but there is something attractive
about have a variable that is simply bound to the external
data source like this. It seems like a good way to encapsulate
functionality that I don't really want the high level class to
have to "think" about.

I mention it here, because I've never seen a property used
this way. So I'm either being very clever, or very dumb,
and I would be interested in opinions on which applies.

Am I about to shoot myself in the foot?

Cheers,
Terry

--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com

 
Reply With Quote
 
 
 
 
Bengt Richter
Guest
Posts: n/a
 
      08-24-2005
On Wed, 24 Aug 2005 01:15:03 -0500, Terry Hancock <(E-Mail Removed)> wrote:

>Frankly, I was surprised this worked at all, but I tried
>creating a property outside of a class (i.e. at the module
>level), and it seems to behave as a property:
>
>>>> def get_x(ob):

>... global x
>... return str(x)
>...
>>>> def set_x(ob, value):

>... global x
>... x = int(value)
>...
>>>> def del_x(ob):

>... global x
>... del x
>...
>>>> def x_access():

>... return property(get_x, set_x, del_x, "X defined externally?")
>...
>>>>
>>>> class Accessor(object):

>... s_x = x_access()
>... def __str__(self):
>... print "Accessor has x = %s" % self.s_X
>...
>>>> a = Accessor()
>>>> a.s_x = 3
>>>> a.s_x

>'3'
>>>> dir()

>['Accessor', '__builtins__', '__doc__', '__name__', 'a', 'del_x', 'get_x', 'p', 'set_x', 'x', 'x_access']
>>>> x

>3
>
>(of course in the real example, x will probably be in an
>entirely different module, used as a library -- the client code
>just calls a function to get a property that is automatically
>managed for it).
>
>So far, the only problem I see is that it only works if the
>property is assigned to a new-type class attribute (otherwise,
>the first assignment simply replaces the property).
>
>I'm thinking of using this to tie a property of a class to an
>external data source (a joystick axis, in fact -- or at least
>its last-polled value).
>
>There is a more convential way to do this, of course -- I could
>just use a "get_value" function, but there is something attractive
>about have a variable that is simply bound to the external
>data source like this. It seems like a good way to encapsulate
>functionality that I don't really want the high level class to
>have to "think" about.
>
>I mention it here, because I've never seen a property used
>this way. So I'm either being very clever, or very dumb,
>and I would be interested in opinions on which applies.
>
>Am I about to shoot myself in the foot?
>

ISTM you are basically exploiting your freedom to define the getter/setter/deleter
functions of a property any way you please. Another way, if you just want a proxy
object whose property attributes access designated other objects' attributes, you
could use a custom descriptor class, e.g.,

>>> class Indirect(object):

... def __init__(self, tgtattr, tgtobj):
... self.tgtattr = tgtattr
... self.tgtobj = tgtobj
... def __get__(self, inst, cls=None):
... if inst is None: return self
... return getattr(self.tgtobj, self.tgtattr)
... def __set__(self, inst, value):
... setattr(self.tgtobj, self.tgtattr, value)
... def __delete__(self, inst):
... delattr(self.tgtobj, self.tgtattr)
...

A place to put properties:
>>> class Accessor(object): pass

...

An example object to access indirectly
>>> class Obj(object): pass

...
>>> obj = Obj()


Making Accessor instance attribute 'xobj' access 'obj' attribute of Obj instance obj
>>> Accessor.xobj = Indirect('obj', obj)


An Accessor instance to use for the property attribute magic
>>> a = Accessor()


Set obj.obj = 123 indirectly
>>> a.xobj = 123


Check
>>> vars(obj)

{'obj': 123}

Set up access to an object attribute in a different module
>>> import sys
>>> Accessor.sin = Indirect('stdin', sys)
>>> a.sin

<open file '<stdin>', mode 'r' at 0x02E8E020>

>>> Accessor.pi = Indirect('pi', __import__('math'))
>>> a.pi

3.1415926535897931
>>> a.pi = 3
>>> a.pi

3
>>> import math
>>> math.pi

3

I'd say there's possibilities for shooting yourself in the foot. Maybe passing
a code to Indirect to enable get/set/del selectively would help.
Regards,
Bengt Richter
 
Reply With Quote
 
 
 
 
Scott David Daniels
Guest
Posts: n/a
 
      08-24-2005
Terry Hancock wrote:
> Frankly, I was surprised this worked at all, but I tried
> creating a property outside of a class (i.e. at the module
> level), and it seems to behave as a property:


Not so surprising. Making a class begins by making a little namespace,
then using it to build the class. If you look at how class construction
works, it gets handed the namespace to wrap parts (the originals are
left alone). After playing with your example for a little, perhaps
the following will illustrate things:

def get_x(obj):
return thevar

def set_x(obj, val):
global thevar
thevar = val

def del_x(obj):
global thevar
del thevar

def textify(obj):
objid = '%s_%s' % (obj.__class__.__name__, id(obj))
try:
return '%s:%r' % (objid, thevar)
except (NameError, AttributeError):
return '%s:---' % objid

prop = property(get_x, set_x, del_x)

class One(object):
x = prop
__repr__ = textify

class Two(object):
y = prop
__str__ = textify

Class Three(object):
__repr__ = textify

a = One()
b = Two()
c = Three()
print a, b, c
a.x = 5
print a.x, b.y, a, b, c
Three.z = One.x
print c, c.z
del b.y
print a, b, c
print a.x

You may want to raise AttributeError on get_x (you have no name to use):
def get_x(obj):
try:
return thevar
except NameError:
raise AttributeError

> Am I about to shoot myself in the foot?


Well, usually all this playing is good for understanding how Python
works, but makes your connections less than explicit, and we know
that explicit is better than implicit.

--Scott David Daniels
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
Michele Simionato
Guest
Posts: n/a
 
      08-25-2005
Well, I have used factories of properties external to the class many
times,
and they work pretty well.

Michele Simionato

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments