Re: How to mix-in __getattr__ after the fact?

2011-11-07 Thread Steven D'Aprano
On Tue, 08 Nov 2011 15:17:14 +1100, Lie Ryan wrote:

> On 10/31/2011 11:01 PM, dhyams wrote:
>>
>> Thanks for all of the responses; everyone was exactly correct, and
>> obeying the binding rules for special methods did work in the example
>> above.  Unfortunately, I only have read-only access to the class itself
>> (it was a VTK class wrapped with SWIG), so I had to find another way to
>> accomplish what I was after.
>>
>>
> As a big huge hack, you can always write a wrapper class:
> 
> class Wrapper(object):
>  def __init__(self, *args, **kwargs):
>  self.__object = MySWIGClass(*args, **kwargs)
>  def __getattr__(self, attr):
>  try:
>  return getattr(self.__object, attr)
>  except AttributeError:
>  ...


That's not a hack, that's a well-respected design pattern called 
Delegation.

http://rosettacode.org/wiki/Delegate
http://en.wikipedia.org/wiki/Delegation_pattern


In this case, you've implemented about half of automatic delegation:

http://code.activestate.com/recipes/52295

which used to be much more important in Python prior to the type/class 
unification in version 2.2.


To also delegate special dunder methods using new-style classes, see this:

http://code.activestate.com/recipes/252151



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to mix-in __getattr__ after the fact?

2011-11-07 Thread Lie Ryan

On 10/31/2011 11:01 PM, dhyams wrote:


Thanks for all of the responses; everyone was exactly correct, and
obeying the binding rules for special methods did work in the example
above.  Unfortunately, I only have read-only access to the class
itself (it was a VTK class wrapped with SWIG), so I had to find
another way to accomplish what I was after.



As a big huge hack, you can always write a wrapper class:

class Wrapper(object):
def __init__(self, *args, **kwargs):
self.__object = MySWIGClass(*args, **kwargs)
def __getattr__(self, attr):
try:
return getattr(self.__object, attr)
except AttributeError:
...

--
http://mail.python.org/mailman/listinfo/python-list


Re: How to mix-in __getattr__ after the fact?

2011-11-01 Thread DevPlayer
On Oct 31, 8:01 am, dhyams  wrote:
> Thanks for all of the responses; everyone was exactly correct, and
> obeying the binding rules for special methods did work in the example
> above.  Unfortunately, I only have read-only access to the class
> itself (it was a VTK class wrapped with SWIG), so I had to find
> another way to accomplish what I was after.
>
Please share what you found as the other way.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to mix-in __getattr__ after the fact?

2011-10-31 Thread dhyams

Thanks for all of the responses; everyone was exactly correct, and
obeying the binding rules for special methods did work in the example
above.  Unfortunately, I only have read-only access to the class
itself (it was a VTK class wrapped with SWIG), so I had to find
another way to accomplish what I was after.

On Oct 28, 10:26 pm, Lie Ryan  wrote:
> On 10/29/2011 05:20 AM, Ethan Furman wrote:
>
>
>
>
>
>
>
>
>
>
>
> > Python only looks up __xxx__ methods in new-style classes on the class
> > itself, not on the instances.
>
> > So this works:
>
> > 8<
> > class Cow(object):
> > pass
>
> > def attrgetter(self, a):
> > print "CAUGHT: Attempting to get attribute", a
>
> > bessie = Cow()
>
> > Cow.__getattr__ = attrgetter
>
> > print bessie.milk
> > 8<
>
> a minor modification might be useful:
>
> bessie = Cow()
> bessie.__class__.__getattr__ = attrgetter

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to mix-in __getattr__ after the fact?

2011-10-28 Thread Lie Ryan

On 10/29/2011 05:20 AM, Ethan Furman wrote:


Python only looks up __xxx__ methods in new-style classes on the class
itself, not on the instances.

So this works:

8<
class Cow(object):
pass

def attrgetter(self, a):
print "CAUGHT: Attempting to get attribute", a

bessie = Cow()

Cow.__getattr__ = attrgetter

print bessie.milk
8<


a minor modification might be useful:

bessie = Cow()
bessie.__class__.__getattr__ = attrgetter


--
http://mail.python.org/mailman/listinfo/python-list


Re: How to mix-in __getattr__ after the fact?

2011-10-28 Thread Ethan Furman

dhyams wrote:

Python 2.7.2

I'm having trouble in a situation where I need to mix-in the
functionality of __getattr__ after the object has already been
created.  Here is a small sample script of the situation:

=snip

import types

class Cow(object):
  pass
  # this __getattr__ works as advertised.
  #def __getattr__(self,a):
  #   print "CAUGHT INCLASS: Attempting to get attribute ",a


def attrgetter(self,a):
   print "CAUGHT: Attempting to get attribute ",a

bessie = Cow()

bessie.__getattr__ = types.MethodType(attrgetter,bessie,Cow)

# here, I should see my printout "attempting to get attribute"
# but I get an AttributeException
print bessie.milk
==snip

If I call __getattr__ directly, as in bessie.__getattr__('foo'), it
works as it should obviously; so the method is bound and ready to be
called.  But Python does not seem to want to call __getattr__
appropriately if I mix it in after the object is already created.  Is
there a workaround, or am I doing something wrongly?

Thanks,


Python only looks up __xxx__ methods in new-style classes on the class 
itself, not on the instances.


So this works:

8<
class Cow(object):
  pass

def attrgetter(self, a):
   print "CAUGHT: Attempting to get attribute", a

bessie = Cow()

Cow.__getattr__ = attrgetter

print bessie.milk
8<

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list


Re: How to mix-in __getattr__ after the fact?

2011-10-28 Thread Jerry Hill
On Fri, Oct 28, 2011 at 1:34 PM, dhyams  wrote:
> If I call __getattr__ directly, as in bessie.__getattr__('foo'), it
> works as it should obviously; so the method is bound and ready to be
> called.  But Python does not seem to want to call __getattr__
> appropriately if I mix it in after the object is already created.  Is
> there a workaround, or am I doing something wrongly?

Python looks up special methods on the class, not the instance (see
http://docs.python.org/reference/datamodel.html#special-method-lookup-for-new-style-classes).

It seems like you ought to be able to delegate the special attribute
access from the class to the instance somehow, but I couldn't figure
out how to do it in a few minutes of fiddling at the interpreter.

-- 
Jerry
-- 
http://mail.python.org/mailman/listinfo/python-list


How to mix-in __getattr__ after the fact?

2011-10-28 Thread dhyams
Python 2.7.2

I'm having trouble in a situation where I need to mix-in the
functionality of __getattr__ after the object has already been
created.  Here is a small sample script of the situation:

=snip

import types

class Cow(object):
  pass
  # this __getattr__ works as advertised.
  #def __getattr__(self,a):
  #   print "CAUGHT INCLASS: Attempting to get attribute ",a


def attrgetter(self,a):
   print "CAUGHT: Attempting to get attribute ",a

bessie = Cow()

bessie.__getattr__ = types.MethodType(attrgetter,bessie,Cow)

# here, I should see my printout "attempting to get attribute"
# but I get an AttributeException
print bessie.milk
==snip

If I call __getattr__ directly, as in bessie.__getattr__('foo'), it
works as it should obviously; so the method is bound and ready to be
called.  But Python does not seem to want to call __getattr__
appropriately if I mix it in after the object is already created.  Is
there a workaround, or am I doing something wrongly?

Thanks,
-- 
http://mail.python.org/mailman/listinfo/python-list