Обновление - 2012/12/13
Просто пояснить - меня не так интересуют способы добавления методов в классы - как вы можете видеть ниже в моем вопросе и в ответах людей, есть более чем один способ сделать это (язык в щеку и кончик шляпы к моему самому Perl).
То, что меня интересует, - это изучение того, что фундаментальное отличие от добавления методов к классам с использованием разных подходов и действительно большой вопрос - почему мне нужно использовать метаклассы. Например, A Primer в Python Metaclass Programming утверждает, что:
Возможно, наиболее распространенное использование метаклассов [...]: добавление, удаление, переименование или замена методов для тех, которые определены в подготовленном классе.
И поскольку есть больше способов сделать это, я озадачен и искал объяснения.
Спасибо!
Оригинал - 2012/12/12
Мне нужно динамически добавлять методы к классу (и вновь созданным классам на основе этого класса). Я придумал два подхода, один из которых касается метакласса, а другой - без него. Я не вижу никакой разницы в том, что два подхода дают мне, кроме того, что последний не связан с метаклассом "черной магии";)
Подход # 1 с метаклассом:
class Meta(type):
def __init__(cls, *args, **kwargs):
setattr(cls, "foo", lambda self: "[email protected]%s(class %s)" % (self,
cls.__name__))
class Y(object):
__metaclass__ = Meta
y = Y()
y.foo() # Gives '[email protected]<__main__.Y object at 0x10e4afd10>(class Y)'
Подход # 2 без метакласса:
class Z(object):
def __init__(self):
setattr(self.__class__, "foo",
lambda self: "[email protected]%s(class %s)" %
(self, self.__class__.__name__))
z = Z()
z.foo() # Gives '[email protected]<__main__.Z object at 0x10c865dd0>(class Z)'
Насколько я могу судить, оба подхода дают мне те же результаты и "выразительность". Даже когда я пытаюсь создать новые классы с помощью type("NewClassY", (Y, ), {})
или type("NewClassZ", (Z, ), {})
, я получаю те же ожидаемые результаты, которые не отличаются между двумя подходами.
Итак, мне интересно, существует ли какая-либо "базовая" разница в подходах, или если есть что-нибудь, что "укусит" меня позже, если я использую либо # 1, либо # 2, или если это просто синтаксический сахар?
PS: Да, я прочитал другие потоки, рассказывая о метаклассах в модели Python и pythonic.