Re: Overriding methods per-object
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
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
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
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
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
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
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
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
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
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
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