2015-04-20 15 views
5

Diciamo che voglio un oggetto personalizzato frozenset con 2 elementi, che esegue iterazioni, hash, confronta e ha varie altre operazioni utili come un frozenset, ma stampa in modo diverso.Personalizzazione di tipi immutabili in Python

>>> p = edge(5, 7) 
>>> p == edge(7, 5) 
True 
>>> p 
edge(5, 7) 

posso ereditare, o posso delegare, ma in nessun caso ottengo quello che voglio.

Se ereditario letteralmente, sembra che non ci sia modo di scrivere __init__, perché il mio genitore è immutabile. Io posso solo scrivere:

class edge: 
    def __new__(cls, a, b): 
     return frozenset({a, b}) 

ma poi ho ottenere un frozenset corretta e non può personalizzare la sua __repr__, che è quello che volevo fare. Non posso fare in modo che super() funzioni qui.

Se si delega, è possibile eseguire l'override di __getattr__ o __getattribute__, ma nessuno di questi funziona realmente quando viene ricercata, ad esempio, __iter__. Immagino che i metodi speciali siano troppo speciali qui. L'unica soluzione che attualmente ho è quella di delegare manualmente ogni metodo speciale che riesco a pensare, ma sicuramente ci deve essere un modo migliore. Qualche idea?

+1

Non sono chiaro cosa vuoi fare. Vuoi solo cambiare '__repr__', o vuoi anche cambiare' __init__'? Perché non hai bisogno di sovrascrivere '__init__' se vuoi solo cambiare' __repr__'. – TheBlackCat

+0

La modifica di '__repr__' era prioritaria. Ma ho pensato che avrei potuto anche cambiare la costruzione di nuovi bordi per rimuovere inutili {} s, quando sto scrivendo una nuova classe. – Veky

risposta

2

Stupido me. Ora funziona. Se qualcuno vuole sapere come farlo, qui è:

class pair(frozenset): 
    def __new__(cls, a, b): 
     return super().__new__(cls, {a, b}) 
    def __repr__(self): 
     a, b = sorted(self) 
     return "{} & {}".format(a, b) 

L'errore è stato che ho chiamato super().__new__({a, b}) pensando che la mia Transmogrify cls nello stesso modo lo fa con self, quando viene chiamato senza argomenti. Naturalmente, __new__ essendo implicitamente classmethod non ha aiutato. :-)