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?
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
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.