Dynamically adding methods to an existing object

This is the place for queries that don't fit in any of the other categories.

Dynamically adding methods to an existing object

Postby volcano63 » Tue Apr 30, 2013 3:44 pm

Hi folks,
I stumbled on a case where I may need to add (and delete) methods to an existing objects dynamically
I tried this - which, to my surprise :o worked
Code: Select all
n [399]: class TestClass(object):
   .....:     def print_val(self):
   .....:         print self.value
   .....:         

In [400]: def set_val(self, val):
   .....:     self.value = val
   .....:     
In [403]: setattr(TestClass, 'set_val', set_val)

In [404]: test_obj.set_val("It's alive")

In [405]: test_obj.print_val()
It's alive

As far as I understand this approach works because methods are accessed through sort of virtual function table (is this the right name?).

My question is - is this a proper way? Or is there more Pythonic way to do that?
Thanks
volcano63
 
Posts: 5
Joined: Sat Apr 20, 2013 11:40 pm

Re: Dynamically adding methods to an existing object

Postby setrofim » Tue Apr 30, 2013 5:45 pm

volcano63 wrote:As far as I understand this approach works because methods are accessed through sort of virtual function table (is this the right name?).

Sort of, but not quite. An instance's attributes (both methods and data members) are contained within a special __dict__ attribute, which basically just a Python dict ( you can verify this in your code by printing out test_obj.__dict__). This means that the members of any instance in Python are not set in stone and can be altered dynamically (this means that even two instances of the same class can have different methods/data -- hence the emphases on duck typing in Python). Classes are themselves instances (everything is an object) so have their own __dict__ member, which is what you are manipulating in your code.

volcano63 wrote:My question is - is this a proper way?

It may be; but probably not. You need to think carefully about what you requirements are.
  • Needing to modify methods at runtime is a "code smell"; this is very error prone, and there is rarely a good reason to do this. I would think carefully about design, e.g. perhaps you should be specifying a callback when instantiating the class or using the Command pattern instead.
  • You're setting the attribute at class level, if you set the same attribute on the instance, that will override what you set on the class (even if you did that earlier):
    Code: Select all
    >>> class Test(object): pass
    ...
    >>> def foo(self):
    ...     print "instance method"
    ...
    >>> def bar(self):
    ...     print "class method"
    ...
    >>> a = Test()
    >>> b = Test()
    >>>
    >>> a.test = foo.__get__(a, Test)
    >>> Test.test = bar
    >>>
    >>> a.test()
    instance method
    >>> b.test()
    class method

    Note that you can't just say "a.test = foo" because methods in Python can be bound or unbound. When you set an attribute of a class (or any object) to a function, you create an unbound method (even if you set an attribute of an instance, it will still be unbound). Complications like these are an example of why you should avoid dynamically messing with methods.
setrofim
 
Posts: 288
Joined: Mon Mar 04, 2013 7:52 pm

Re: Dynamically adding methods to an existing object

Postby volcano63 » Wed May 01, 2013 6:45 am

Thanks
Just checking ideas
volcano63
 
Posts: 5
Joined: Sat Apr 20, 2013 11:40 pm


Return to General Coding Help

Who is online

Users browsing this forum: Google [Bot], physicist, thunderspeed and 2 guests