On Thu, 03 Dec 2009 23:12:39 -0600, Brad Harms wrote: > On Tue, 2009-12-01 at 14:38 +0000, Steven D'Aprano wrote: [...] >> It's just special double-underscore methods like __init__ __add__ etc >> that have to be in the class rather than the instance. (To be precise, >> you can add such a method to the instance, but it won't be called >> automatically.) Likewise staticmethods and classmethods won't work >> correctly unless they are in the class. But ordinary methods work fine: >> the only tricky bit is creating them in the first place. >> >> >>> class K(object): >> ... pass >> ... >> >>> k = K() >> >>> import types >> >>> k.method = types.MethodType(lambda self: "I am %s" % self, k) >> >>> k.method() >> 'I am <__main__.K object at 0xb7cc7d4c>' > > ...I'm not sure I follow your logic. > > Yes, you can create an instancemethod out of a function and assign it to > an instance after (or during) its instantiation, which is what Python's > class/instance model provides automatically. However, to do so manually > in this manner completely disregards the fundamentals of object-oriented > programming, not to mention the basic guiding principles of nearly all > Python code in existence. It totally breaks inheritance and > polymorphism. Maybe I'm missing something, but I can't see how that line > of thought helps anything.
I'm not recommending it as a standard technique instead of defining methods via the usual class statement. But it does work, and can be handy for the odd occasion where you want per-instance behaviour of some class. I'm not saying this is a common occurrence, but it does happen -- it's particularly handy if you have a standard behaviour which you want to override, e.g. monkey-patching specific instances. Instead of this: class K: marker = None def method(self): if self.marker: return "special" return "normal" k = K() k.marker = 1 you can do this: class K: def method(self): return "normal" k = K() k.method = type(k.method)(lambda self: "special", k) So although unusual, it is useful. As for breaking inheritance and polymorphism, not at all. Inheritance still works, and polymorphism is irrelevant: methods are, or aren't, polymorphic regardless of whether they are per instance or shared. Fundamentally, per-instance methods are nothing more than as per-instance attributes which happen to be callable. It is "magic methods" like __len__ and friends that break the usual rules of inheritance. The normal lookup chain for instance.name, whether name is a callable method or a non-callable attribute, is: instance class base class(es) but for magic methods, the chain skips the instance step. That's done as an optimization, and given how rare it is to have per-instance methods, that's quite reasonable. -- Steven -- http://mail.python.org/mailman/listinfo/python-list