2010-05-18 13 views
12

Ho scritto un tipo di contenitore in Python e sto provando a scrivere un robusto metodo __repr__ che gestisce correttamente il caso in cui il contenitore contiene se stesso.Come gestisco recursive repr() in Python?

Per esempio, ecco cosa il built-in list fa: tipi

>>> x = [] 
>>> x.append(x) 
>>> repr(x) 
'[[...]]' 

container scritti in C per CPython possono ottenere questa funzionalità utilizzando Py_ReprEnter e Py_ReprLeave. Esiste funzionalità equivalenti in pure-Python o devo creare il mio?

risposta

6

È possibile creare il proprio, ma è un po 'un problema se si vuole farlo correttamente: non si deve memorizzare un flag di "essere repr'd" sull'oggetto stesso perché non è thread-safe. Invece è possibile memorizzare un set locale di thread delle istanze che vengono rimosse.

Una soluzione molto più economica è dipendere da un incorporato repr che si occupa di ricorsione, es .:

def __init__(self, *list): 
    self._list= list 
def __repr__(self): 
    return 'mything('+repr(self._list)[1:-1]+')') 

Fintanto uno oggetto in un ciclo ricorsione causa sindrome Py_ReprEnter accada, repr non può formare un ciclo completo.

Come si crea un set locale di thread di istanze?

Con il modulo threading:

class MyThing(object): 
    _local= threading.local() 
    _local.reprs= set() 

    def __repr__(self): 
     reprs= MyThing._local.reprs 
     sid= id(self) 
     if sid in reprs: 
      return 'MyThing(...)' 
     try: 
      reprs.add(sid) 
      return 'MyThing(%r)' % self.something 
     finally: 
      reprs.remove(sid) 
+0

Sfortunatamente, devo calcolare la stringa di repr in modo dinamico, quindi non posso dipendere dal built-in repr() nel modo in cui descrivi. Come posso creare un set di istanze thread-local? –

+0

@DanielStutzbach, perché avvolto nel blocco try/finally? – akaRem

+1

@akaRem: 'self.something' è un segnaposto per un lavoro più complesso che coinvolge la ricorsione. In una brutta giornata qualcosa in là potrebbe causare un'eccezione. Se ciò accade, vogliamo assicurarci che la lista di 'reprs' venga cancellata al contrario, altrimenti accumulerà istanze man mano che gli errori si accumulano, causando sempre più' MyThing's da render come 'MyThing (...) 'anche quando non c'è ricorsione. – bobince

Problemi correlati