更新 - 2012/12/13
为了澄清一下 - 我的兴趣并不在于如何将方法添加到类中 - 如您可以在我的问题和人们的答案中看到的那样,有多种方法可以做到这一点(对自己的 Perl 深表歉意)。
我感兴趣的是学习使用不同方法向类添加方法的基本区别,而真正的大问题是为什么我需要使用元类。例如 Python 元类编程入门 指出:
可能是元类最常见的用途 [...]:添加、删除、重命名或替换已定义的类中的方法。
由于有更多的方法可以实现这一点,我感到困惑并正在寻找解释。
谢谢!
原始内容- 2012/12/12
我需要动态地向类(以及基于该类生成的新类)添加方法。我提出了两种方法,一种涉及元类,另一种则不需要。除了后者没有涉及“黑魔法”元类之外,我无法看出这两种方法给我带来任何区别 ;)
方法 1 #1 使用元类:
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)'
第二种方法,#2 没有元类:
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)'
据我所知,这两种方法在结果和“表现力”方面都是相同的。即使我尝试使用 type("NewClassY", (Y, ), {})
或者 type("NewClassZ", (Z, ), {})
来创建一个新类,我也会得到相同的预期结果,这两种方法之间没有区别。因此,我想知道这两种方法是否存在任何“潜在”的差异,或者如果我使用#1或#2是否会有什么问题,或者这只是一种语法糖?
PS:是的,我确实读了这里讨论Python元类和Pythonic数据模型的其他线程。
Y.foo
和Z.foo
吗? - Blender__init__
方式将在实例化类时创建方法。还有多重继承(mixin),您可以使用它来添加方法。 - Jochen Ritzel