Adding bound methods dynamically...
#!/usr/bin/env python ''' I want to dynamically add or replace bound methods in a class. I want the modifications to be immediately effective across all instances, whether created before or after the class was modified. I need this to work for both old ('classic') and new style classes, at both 2.3 and 2.4. I of course want to avoid side effects, and to make the solution as light-weight as possible. Question for the experts: Is the solution coded in AddBoundMethod() acceptable to the Pythonian Gods? :) It does seem to work -- tested at 2.3.5 (RH Linux) and 2.4.1 (WinXP) Is there a more pythonic way that's as straight forward? ''' def AddBoundMethod( cls, name, method ): ''' Dynamically add to the class 'cls' a bound method. Invoking this method instantly adds (or overwrites) the bound method identified by 'name' with the code contained in 'method', EVEN FOR PRE-EXISTING INSTANCES OF THE CLASS. The 'method' parameter should be a non-class function that has 'self' as its first parameter. ''' try: types except NameError: import types # # this is the crux of this example, short and sweet... # exec "%s.%s = types.MethodType( method, None, %s )" \ % ( cls.__name__, name, cls.__name__ ) # # The remainder (50x longer than the solution!) is test code... # # one new-style class... class NewStyleClass( object ): def __init__ ( self, objname ): print "Created a NewStyleClass, id %d, %s" % \ ( id( self ), objname ) self.objname = objname def ExistingMethod( self, msg ): print "Original ExistingMethod, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) # one 'classic' style class... class OldStyleClass: def __init__ ( self, objname ): print "Created a OldStyleClass, id %d, %s" % \ ( id( self ), objname ) self.objname = objname def ExistingMethod( self, msg ): print "Original ExistingMethod, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) # two non-class functions that *look* like bound methods in a class; # one returns a value, the other just outputs a string... def NeverInOriginalClass( self, msg ): return "Never in original class, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) def NewExistingMethod( self, msg ): print "REPLACED ExistingMethod, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) # a test routine... def Test( cls ): print "--- %s --" % \ cls.__name__ print "type of class %s is '%s'" % ( cls.__name__, type( cls ) ) before_change = cls('instance created before change') print "type of object before_change is '%s'" % type(before_change) # 'A' shows that we start with an existing method before_change.ExistingMethod( 'A' ) print "*** Replacing bound method 'ExistingMethod'..." AddBoundMethod( cls, "ExistingMethod", NewExistingMethod ) after_change = cls( 'instance created AFTER change' ) print "type of after_change is '%s'" % type( after_change ) # 'B' and 'C' show we've replaced an existing method, both on # pre-existing instances and instances created after using # AddBoundMethod() before_change.ExistingMethod( 'B' ) after_change.ExistingMethod( 'C' ) print "*** Adding new bound method 'AddedMethod'..." AddBoundMethod( after_change.__class__, "AddedMethod", NeverInOriginalClass ) # 'D' and 'E' show we've added a brand new method, both on # pre-existing instances and instances created after using # AddBoundMethod() print "%s" % before_change.AddedMethod( 'D' ) print "%s" % after_change.AddedMethod( 'E' ) if __name__ == '__main__': Test( OldStyleClass ) Test( NewStyleClass ) -- http://mail.python.org/mailman/listinfo/python-list
Re: Adding bound methods dynamically... CORRECTED
#!/usr/bin/env python # Sorry... :} cut/paste error fixed... ''' I want to dynamically add or replace bound methods in a class. I want the modifications to be immediately effective across all instances, whether created before or after the class was modified. I need this to work for both old ('classic') and new style classes, at both 2.3 and 2.4. I of course want to avoid side effects, and to make the solution as light-weight as possible. Question for the experts: Is the solution coded in AddBoundMethod() acceptable to the Pythonian Gods? :) It does seem to work -- tested at 2.3.5 (RH Linux) and 2.4.1 (WinXP) Is there a more pythonic way that's as straight forward? ''' def AddBoundMethod( cls, name, method ): ''' Dynamically add to the class 'cls' a bound method. Invoking this method instantly adds (or overwrites) the bound method identified by 'name' with the code contained in 'method', EVEN FOR PRE-EXISTING INSTANCES OF THE CLASS. The 'method' parameter should be a non-class function that has 'self' as its first parameter. ''' try: types except NameError: import types # # this is the crux of this example, short and sweet... # exec "%s.%s = types.MethodType( method, None, %s )" \ % ( cls.__name__, name, cls.__name__ ) # # The remainder (50x longer than the solution!) is test code... # # one new-style class... class NewStyleClass( object ): def __init__ ( self, objname ): print "Created a NewStyleClass, id %d, %s" % \ ( id( self ), objname ) self.objname = objname def ExistingMethod( self, msg ): print "Original ExistingMethod, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) # one 'classic' style class... class OldStyleClass: def __init__ ( self, objname ): print "Created a OldStyleClass, id %d, %s" % \ ( id( self ), objname ) self.objname = objname def ExistingMethod( self, msg ): print "Original ExistingMethod, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) # two non-class functions that *look* like bound methods in a class; # one returns a value, the other just outputs a string... def NeverInOriginalClass( self, msg ): return "Never in original class, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) def NewExistingMethod( self, msg ): print "REPLACED ExistingMethod, id %d, %s: '%s'" % \ ( id( self ), self.objname, msg ) # a test routine... def Test( cls ): print "--- %s --" % \ cls.__name__ print "type of class %s is '%s'" % ( cls.__name__, type( cls ) ) before_change = cls('instance created before change') print "type of object before_change is '%s'" % type(before_change) # 'A' shows that we start with an existing method before_change.ExistingMethod( 'A' ) print "*** Replacing bound method 'ExistingMethod'..." AddBoundMethod( cls, "ExistingMethod", NewExistingMethod ) after_change = cls( 'instance created AFTER change' ) print "type of after_change is '%s'" % type( after_change ) # 'B' and 'C' show we've replaced an existing method, both on # pre-existing instances and instances created after using # AddBoundMethod() before_change.ExistingMethod( 'B' ) after_change.ExistingMethod( 'C' ) print "*** Adding new bound method 'AddedMethod'..." AddBoundMethod( after_change.__class__, "AddedMethod", NeverInOriginalClass ) # 'D' and 'E' show we've added a brand new method, both on # pre-existing instances and instances created after using # AddBoundMethod() print "%s" % before_change.AddedMethod( 'D' ) print "%s" % after_change.AddedMethod( 'E' ) if __name__ == '__main__': Test( OldStyleClass ) Test( NewStyleClass ) -- http://mail.python.org/mailman/listinfo/python-list
Hooking any/all 'calls'
In Python 2.4 or 2.5, what is the easiest way to hook any and all callables such that designated code is executed at the very start and end of each call? (Yes, I'm trying to come up with a little debugging tool!:) Is there a single metaclass who's "__call__" method can be wrapped to do this? TIA, -k -- http://mail.python.org/mailman/listinfo/python-list
Re: Hooking any/all 'calls'
Thanks, Robert! That was exactly what I was looking for. -k "fumanchu" <[EMAIL PROTECTED]> wrote: >Kevin Little wrote: >> In Python 2.4 or 2.5, what is the easiest way to hook any and all >> callables such that designated code is executed at the very start and >> end of each call? (Yes, I'm trying to come up with a little debugging >> tool!:) Is there a single metaclass who's "__call__" method can be >> wrapped to do this? > >You probably want sys.settrace, which is specifically designed for >creating debuggers, and is the basis for pdb, the debugger in the >standard library. See >http://docs.python.org/lib/module-sys.html#l2h-5159 > >Feel free also to look through my own debugging aid (for clues on how >to implement your own, or just to use for your needs): >http://projects.amor.org/misc/wiki/PyConquer > > >Robert Brewer >System Architect >Amor Ministries >[EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list