Update - 2012/12/13
Just to clarify - I'm not so much interested in ways how to add methods to classes - as you can see below in my question and in people's answers, there is more than one way to do that (tongue in cheek and hat tip to my Perl self).
The thing I am interested in is learning what's the fundamental difference of adding methods to classes using different approaches and the big question really is why do I need to use metaclasses for. For example A Primer on Python Metaclass Programming states that:
Perhaps the most common use of metaclasses [...]: adding, deleting, renaming, or substituting methods for those defined in the produced class.
And since there's more ways to do that, I'm puzzled and looking for explanation.
Thanks!
Original - 2012/12/12
I need to dynamically add methods to a class (and newly generated classes based on that class). I came up with two approaches, one involving metaclass, the other one doing without one. I cannot see any difference in what the two approaches give me other than the fact the latter doesn't involve the "black magic" metaclass ;)
Approach #1 with metaclass:
class Meta(type):
def __init__(cls, *args, **kwargs):
setattr(cls, "foo", lambda self: "foo@%s(class %s)" % (self,
cls.__name__))
class Y(object):
__metaclass__ = Meta
y = Y()
y.foo() # Gives 'foo@<__main__.Y object at 0x10e4afd10>(class Y)'
Approach #2 without metaclass:
class Z(object):
def __init__(self):
setattr(self.__class__, "foo",
lambda self: "foo@%s(class %s)" %
(self, self.__class__.__name__))
z = Z()
z.foo() # Gives 'foo@<__main__.Z object at 0x10c865dd0>(class Z)'
As far as I can tell, both approaches give me the same results and "expressivity". Even when I try to create a new classes using type("NewClassY", (Y, ), {})
or type("NewClassZ", (Z, ), {})
I get the same expected results which don't differ between the two approaches.
So, I'm wondering if there really is any "underlying" difference in the approaches, or if there's anything which will "bite" me later if I used either #1 or #2 or if it's just a syntactic sugar?
PS: Yes, I did read the other threads here talking about metaclasses in Python and pythonic data model.
Y.foo
andZ.foo
using both approaches? – Blender Dec 12 '12 at 23:15__init__
way will create the methods when you instantiate the class. There is also multiple inheritance (mixins) which you can use to add methods. – Jochen Ritzel Dec 12 '12 at 23:24