2009-11-22 17 views

risposta

34

I decoratori sono molto, molto più semplici e più limitati - e quindi dovrebbero essere preferiti ogni volta che l'effetto desiderato può essere raggiunto con un metaclasse o un decoratore di classe.

Qualsiasi cosa tu possa fare con un decoratore di classe, puoi ovviamente fare con un metaclass personalizzato (basta applicare la funzionalità della "funzione decoratore", cioè quella che prende un oggetto di classe e lo modifica, nel corso del metacarattere __new__ o __init__ che rendono l'oggetto classe! -).

Ci sono molte cose che puoi fare in un metaclasse personalizzato ma non in un decoratore (a meno che il decoratore non generi e applichi internamente un metaclasse personalizzato, ovviamente - ma questo è imbroglio; -) ... e anche allora, in Python 3, ci sono cose che puoi fare solo con un metaclasse personalizzato, non dopo il fatto ... ma questa è una sub-nicchia abbastanza avanzata della tua domanda, quindi lasciatemi dare esempi più semplici).

Per esempio, supponiamo di voler fare un oggetto di classe X tale che print X (o in Python 3 print(X) ovviamente ;-) mostra peekaboo!. Non è possibile farlo senza un metaclasse personalizzato, perché l'override di metrame di __str__ è l'attore cruciale qui, cioè, è necessario un def __str__(cls): return "peekaboo!" nel metaclass personalizzato della classe X.

Lo stesso vale per tutti i metodi magici, cioè, a tutti i tipi di operazioni applicati all'oggetto classe stessa (a differenza, quelli applicato al suo istanze, che utilizzano metodi magici come definito nella classe - le operazioni sull'oggetto classe stesso usano metodi magici come definito nel metaclass).

+0

risposta interessante da connazionale eminente =) – gpilotino

+0

Ciao gino, sempre particolarmente contento di aiutare un connazionale ovviamente ;-). –

+6

Beh .. sono passati 4 anni e ho trovato questa domanda su google. Voglio solo prendere nota del tuo esempio. Ho definito un decoratore 'foo (cls)' che ha 2 istruzioni: 'cls .__ str__ = lambda self:" peekaboo! "' E subito dopo 'return cls', e in effetti ha funzionato - Ho impostato il' metodo __str__' di qualche classe con il decoratore piuttosto che con un metaclasse complicato .. Volevo solo prenderlo in considerazione, e magari ottenere qualche commento per sapere se mi manca qualcosa. – rboy