2010-01-30 5 views
16

Come si verifica se un oggetto è un'istanza di Named tuple?Python: come verificare se un oggetto è un'istanza di un namedtuple?

+0

Avete bisogno di sapere assolutamente, o è un'euristica va bene? Se quest'ultimo, puoi controllare ad es. obj._asdict .__ doc__ == 'Restituisce un nuovo OrderedDict che associa i nomi dei campi ai loro valori' (eventualmente anche altri fattori). –

+0

Assolutamente, certo. Ma dato che userò questo "check" solo in una dichiarazione "assert'" (sto scrivendo un'estensione a namedtuples .. che mixin asserisce che è usato con un namedtuple come classe di base di pari livello), il controllo euristico potrebbe anche essere bene. Penso che valga la pena aggiungere il tuo controllo '__doc__' al codice di Alex sotto. –

+4

FWIW, questo è archiviato come un "bug" (non sono sicuro che sia d'accordo): http://bugs.python.org/issue7796 – bernie

risposta

19

Chiamando la funzionecollections.namedtupleti dà un nuovo tipo che è una sottoclasse di tuple (e non altre classi) con un membro denominato _fields che è una tupla i cui elementi sono tutte le stringhe. Così si potrebbe verificare la presenza di tutti e di ciascuno di queste cose:

def isnamedtupleinstance(x): 
    t = type(x) 
    b = t.__bases__ 
    if len(b) != 1 or b[0] != tuple: return False 
    f = getattr(t, '_fields', None) 
    if not isinstance(f, tuple): return False 
    return all(type(n)==str for n in f) 

è possibile ottenere un falso positivo da questo, ma solo se qualcuno sta andando fuori del loro modo di fare un tipo che sembra molto come una tupla chiamata ma non è una ;-).

+0

corretto. Mi chiedevo anche perché il tipo generato non fosse derivato da una classe di marcatori 'NamedTuple' la cui definizione sarebbe semplicemente' class NamedTuple (tuple): pass' .. solo per rendere più facile per noi controllare se un oggetto è un namedtuple o non. –

+2

Perché i designer di namedtuple dovrebbero renderlo tipografico, Sridhar? Typeckecking è generalmente da evitare in Python e in questo caso non ti dice nulla di utile - una namedtuple con campi 'x' e' y' e una con campi 'costo',' prezzo' e 'quantità' aren Saranno intercambiabili. L'unico livello a cui sono intercambiabili è che si tratta di entrambe le tuple. Anche nel caso d'uso di lavorare con le classi generate dalla fabbrica namedtuple, sono solo classi normali per una buona ragione e possono essere utilizzate proprio come una classe simile fatta a mano. –

+0

@Mike: Sto scrivendo un'estensione alle tuple denominate .. che mixin asserisce che è usato con una tupla chiamata come classe base di pari livello. Quindi, ne ho solo bisogno per affermare che il mixin non viene utilizzato in modo improprio con altri tipi. –

3

Se è necessario verificare prima di chiamare funzioni specifiche di namedtuple, basta chiamarli e catturare l'eccezione. Questo è il modo preferito per farlo in Python.

+0

La mia risposta a Matthew sopra spiega dove sto usando questo controllo. –

0

Io uso

isinstance(x, tuple) and isinstance(x.__dict__, collections.abc.Mapping) 

che a me sembra riflettere meglio l'aspetto dizionario della natura di tuple nome. Sembra robusto anche contro alcune future modifiche e potrebbe anche funzionare con molte classi namedtuple di terze parti, se queste cose accadono.

+1

Ciò causerà un errore quando 'x = (1,2,3)' – kolypto

3

Mi rendo conto che è vecchio, ma ho trovato questo utile:

from collections import namedtuple 

SomeThing = namedtuple('SomeThing', 'prop another_prop') 
SomeOtherThing = namedtuple('SomeOtherThing', 'prop still_another_prop') 

a = SomeThing(1, 2) 

isinstance(a, SomeThing) # True 
isinstance(a, SomeOtherThing) # False 
+0

A meno che non manchi qualcosa, questa sembra la risposta migliore e più concisa. Un namedtuple crea un nuovo tipo e isinstance controllerà se qualcosa è quel tipo. –

Problemi correlati