On Wed, 24 Aug 2005 01:15:03 -0500, Terry Hancock <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list