Update - 2012/12/13dinamicamente aggiungendo metodi con o senza metaclasse
Giusto per chiarire - io non sono tanto interessati a modi come aggiungere metodi alle classi - come potete vedere qui sotto nella mia domanda e nelle risposte delle persone, c'è più di un modo per farlo (lingua in bocca e punta di cappello al mio io Perl).
La cosa a cui sono interessato è imparare qual è la differenza fondamentale di aggiungere metodi alle classi utilizzando approcci diversi e la grande domanda è davvero il motivo per cui ho bisogno di utilizzare i metaclassi per. Per esempio A Primer on Python Metaclass Programming afferma che:
Forse l'uso più comune di metaclassi [...]: aggiungere, cancellare, rinominare, o sostituendo i metodi per quelli definiti nella classe prodotta.
E dal momento che ci sono altri modi per farlo, sono perplesso e in cerca di spiegazioni.
Grazie!
originale - 2012/12/12
ho bisogno di aggiungere dinamicamente i metodi di una classe (e le classi di nuova generate sulla base di quella classe). Ho trovato due approcci, uno che riguarda la metaclasse, l'altro uno senza. Non riesco a vedere alcuna differenza in quello che i due approcci danno me a parte il fatto quest'ultimo non comporta la metaclasse "magia nera";)
Approccio # 1con metaclasse:
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)'
approccio # 2senza metaclasse:
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)'
Per quanto posso dillo, entrambi gli approcci mi danno gli stessi risultati e "espressività". Anche quando provo a creare una nuova classe usando type("NewClassY", (Y,), {})
o type("NewClassZ", (Z,), {})
ottengo gli stessi risultati attesi che non differiscono tra i due approcci.
Quindi, mi chiedo se c'è davvero nessuna differenza "sottostante" negli approcci, o se c'è qualcosa che vi "morso" me più tardi se ho usato sia # 1 o # 2 o se è solo uno zucchero sintattico?
PS: Sì, ho letto gli altri thread qui parlando di metaclassi in Python e modello di dati pythonic.
Puoi chiamare 'Y.foo' e' Z.pippo' usando entrambi gli approcci? – Blender
La differenza è che il metaclass creerà i metodi al momento della definizione della classe e '__init__'way creerà i metodi quando istanziate la classe. Esiste anche un'ereditarietà multipla (mixins) che è possibile utilizzare per aggiungere metodi. –
@Blender No, non puoi chiamarli così poiché non sono "metodi di classe". – TomasHeran