Re: Overriding methods per-object

2009-04-19 Thread Pavel Panchekha
On Apr 18, 9:43 pm, Aaron Brady castiro...@gmail.com wrote:
 On Apr 17, 9:41 pm, Steven D'Aprano st...@remove-this-

 cybersource.com.au wrote:
  On Fri, 17 Apr 2009 18:22:49 -0700, Pavel Panchekha wrote:
   I've got an object which has a method, __nonzero__ The problem is, that
   method is attached to that object not that class

   a = GeneralTypeOfObject()
   a.__nonzero__ = lambda: False
   a.__nonzero__()
   False

   But:

   bool(a)
   True

   What to do?

  (1) Don't do that.

  (2) If you *really* have to do that, you can tell the class to look at
  the instance:

  class GeneralTypeOfObject(object):
      def __nonzero__(self):
          try:
              return self.__dict__['__nonzero__']
          except KeyError:
              return something

 snip

 I think you need to call the return, unlike you would in
 '__getattr__'.
              return self.__dict__['__nonzero__']( )

 You're free to use a different name for the method too.
              return self.custom_bool( )

 And you don't even have to implement an ABC.  Er... /have/ to, that
 is.

I got it working. Thanks!
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-18 Thread Piet van Oostrum
 Pavel Panchekha pavpanche...@gmail.com (PP) wrote:

 The docs don't say you can do that:
PP Thanks, hadn't noticed that.

 Should you be able to?

PP I'd say so. In my case, I need a class that can encapsulate any
PP object, add a few methods to it, and spit something back that works
PP just like the object, but also has those extra methods. I can't just
PP add the methods, because it has to work on e.g. lists. So I'll have to
PP end up defining all the possible methods on that class (and that's
PP still not best because I can't use hasattr to test if, for example,
PP addition is allowed on that object).

PP On the other hand, I see how this severely restricts the possibly
PP optimizations that can be made in the interpreter.

But you can give each object its own class and then put the special
methods in that class:

 def create_special_object(bases, *args):
...   if not isinstance(bases, tuple):
...  bases = bases,
...   cls = type(SpecialClass, bases, {})
...   return cls(*args)
... 
 a = create_special_object(list, [1,2,3])
 a
[1, 2, 3]
 a.__class__
class '__main__.SpecialClass'
 a.__class__.__nonzero__ = lambda self: False
 bool(a)
False
 a.__nonzero__()
False
 a.append(4)
 a
[1, 2, 3, 4]
 

-- 
Piet van Oostrum p...@cs.uu.nl
URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4]
Private email: p...@vanoostrum.org
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-18 Thread Pavel Panchekha
On Apr 18, 4:01 pm, Piet van Oostrum p...@cs.uu.nl wrote:
 But you can give each object its own class and then put the special
 methods in that class:

  def create_special_object(bases, *args):

 ...   if not isinstance(bases, tuple):
 ...      bases = bases,
 ...   cls = type(SpecialClass, bases, {})
 ...   return cls(*args)
 ... a = create_special_object(list, [1,2,3])
  a
 [1, 2, 3]
  a.__class__

 class '__main__.SpecialClass'

  a.__class__.__nonzero__ = lambda self: False
  bool(a)
 False
  a.__nonzero__()
 False
  a.append(4)
  a
 [1, 2, 3, 4]

 --
 Piet van Oostrum p...@cs.uu.nl
 URL:http://pietvanoostrum.com[PGP 8DAE142BE17999C4]
 Private email: p...@vanoostrum.org

I think this is the solution I like best.

 FYI this works as you expect if GeneralTypeOfObject is an old-style
 class (i.e. does not inherit from object). If this feature is so more
 important than all those that come with new-style classes, you have
 control over the involved classes and don't care about Python 3.x
 (where old-style classes are gone), you may choose to downgrade
 GeneralTypeOfObject to old-style.

It is important, but new-style classes are important too. And I care
quite a bit about Python 3.x, thus the fact that I prefer the above
solution.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-18 Thread Gabriel Genellina
En Sat, 18 Apr 2009 19:39:24 -0300, Pavel Panchekha  
pavpanche...@gmail.com escribió:

On Apr 18, 4:01 pm, Piet van Oostrum p...@cs.uu.nl wrote:



But you can give each object its own class and then put the special
methods in that class:

 def create_special_object(bases, *args):

...   if not isinstance(bases, tuple):
...      bases = bases,
...   cls = type(SpecialClass, bases, {})
...   return cls(*args)
... a = create_special_object(list, [1,2,3])
 a
[1, 2, 3]
 a.__class__

class '__main__.SpecialClass'

 a.__class__.__nonzero__ = lambda self: False
 bool(a)
False


I think this is the solution I like best.


You may want to implement some kind of cache: creating a new class for  
every instance is expensive.

Also, note that those instances are not pickleable.

--
Gabriel Genellina

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


Re: Overriding methods per-object

2009-04-18 Thread Aaron Brady
On Apr 17, 9:41 pm, Steven D'Aprano st...@remove-this-
cybersource.com.au wrote:
 On Fri, 17 Apr 2009 18:22:49 -0700, Pavel Panchekha wrote:
  I've got an object which has a method, __nonzero__ The problem is, that
  method is attached to that object not that class

  a = GeneralTypeOfObject()
  a.__nonzero__ = lambda: False
  a.__nonzero__()
  False

  But:

  bool(a)
  True

  What to do?

 (1) Don't do that.

 (2) If you *really* have to do that, you can tell the class to look at
 the instance:

 class GeneralTypeOfObject(object):
     def __nonzero__(self):
         try:
             return self.__dict__['__nonzero__']
         except KeyError:
             return something
snip

I think you need to call the return, unlike you would in
'__getattr__'.
 return self.__dict__['__nonzero__']( )

You're free to use a different name for the method too.
 return self.custom_bool( )

And you don't even have to implement an ABC.  Er... /have/ to, that
is.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-17 Thread Chris Rebert
On Fri, Apr 17, 2009 at 6:22 PM, Pavel Panchekha pavpanche...@gmail.com wrote:
 I've got an object which has a method, __nonzero__
 The problem is, that method is attached to that object not that class

 a = GeneralTypeOfObject()
 a.__nonzero__ = lambda: False
 a.__nonzero__()
 False

 But:

 bool(a)
 True

This is as documented. See
http://docs.python.org/3.0/reference/datamodel.html#special-lookup


 What to do?

Either wrap the object in another object of a class that does define
__bool__, or change GeneralTypeOfObject so it defines __bool__(),
possibly having its __bool__ delegate to another method, which you
could then override on a per-object basis similar to your current
code.

Cheers,
Chris
-- 
I have a blog:
http://blog.rebertia.com
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-17 Thread Aaron Brady
On Apr 17, 8:22 pm, Pavel Panchekha pavpanche...@gmail.com wrote:
 I've got an object which has a method, __nonzero__
 The problem is, that method is attached to that object not that class

  a = GeneralTypeOfObject()
  a.__nonzero__ = lambda: False
  a.__nonzero__()

 False

 But:

  bool(a)

 True

 What to do?

The docs don't say you can do that:

Special method names
A class can implement certain operations that are invoked by special
syntax (such as arithmetic operations or subscripting and slicing) by
defining methods with special names.

Should you be able to?
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-17 Thread Pavel Panchekha
 The docs don't say you can do that:

Thanks, hadn't noticed that.

 Should you be able to?

I'd say so. In my case, I need a class that can encapsulate any
object, add a few methods to it, and spit something back that works
just like the object, but also has those extra methods. I can't just
add the methods, because it has to work on e.g. lists. So I'll have to
end up defining all the possible methods on that class (and that's
still not best because I can't use hasattr to test if, for example,
addition is allowed on that object).

On the other hand, I see how this severely restricts the possibly
optimizations that can be made in the interpreter.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-17 Thread Aaron Brady
On Apr 17, 9:28 pm, Pavel Panchekha pavpanche...@gmail.com wrote:
  The docs don't say you can do that:

 Thanks, hadn't noticed that.

  Should you be able to?

 I'd say so. In my case, I need a class that can encapsulate any
 object, add a few methods to it, and spit something back that works
 just like the object, but also has those extra methods. I can't just
 add the methods, because it has to work on e.g. lists. So I'll have to
 end up defining all the possible methods on that class (and that's
 still not best because I can't use hasattr to test if, for example,
 addition is allowed on that object).

 On the other hand, I see how this severely restricts the possibly
 optimizations that can be made in the interpreter.

Can you dynamically subclass it:

def subclasser( obj ):
  class newclass( obj.__class__ ):
def __nonzero__.
  obj.__class__= newclass

FYI, the __class__ member is assignable, though I've personally never
done it in practice.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Overriding methods per-object

2009-04-17 Thread Steven D'Aprano
On Fri, 17 Apr 2009 18:22:49 -0700, Pavel Panchekha wrote:

 I've got an object which has a method, __nonzero__ The problem is, that
 method is attached to that object not that class
 
 a = GeneralTypeOfObject()
 a.__nonzero__ = lambda: False
 a.__nonzero__()
 False
 
 But:
 
 bool(a)
 True
 
 What to do?

(1) Don't do that.

(2) If you *really* have to do that, you can tell the class to look at 
the instance:

class GeneralTypeOfObject(object):
def __nonzero__(self):
try:
return self.__dict__['__nonzero__']
except KeyError:
return something

(3) But a better solution might be to subclass the class and use an 
instance of that instead. You can even change the class on the fly.

a.__class__ = SubclassGeneralTypeOfObject  # note the lack of brackets




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


Re: Overriding methods per-object

2009-04-17 Thread George Sakkis
On Apr 17, 9:22 pm, Pavel Panchekha pavpanche...@gmail.com wrote:

 I've got an object which has a method, __nonzero__
 The problem is, that method is attached to that object not that class

  a = GeneralTypeOfObject()
  a.__nonzero__ = lambda: False
  a.__nonzero__()

 False

 But:

  bool(a)

 True

 What to do?


FYI this works as you expect if GeneralTypeOfObject is an old-style
class (i.e. does not inherit from object). If this feature is so more
important than all those that come with new-style classes, you have
control over the involved classes and don't care about Python 3.x
(where old-style classes are gone), you may choose to downgrade
GeneralTypeOfObject to old-style.

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