Determinare il tipo di un oggetto?

C'è un modo semplice per determinare se una variabile è una lista, un dizionario o qualcos'altro? Sto ricevendo un oggetto che può essere di entrambi i tipi e ho bisogno di essere in grado di capire la differenza.

Soluzione

Per ottenere il tipo di un oggetto, potete usare la funzione built-in type(). Passando un oggetto come unico parametro restituirà il tipo di quell'oggetto:

>>> type([]) is list
True
>>> type({}) is dict
True
>>> type('') is str
True
>>> type(0) is int
True
>>> type({})

>>> type([])

Questo naturalmente funziona anche per i tipi personalizzati:

>>> class Test1 (object):
        pass
>>> class Test2 (Test1):
        pass
>>> a = Test1()
>>> b = Test2()
>>> type(a) is Test1
True
>>> type(b) is Test2
True

Notate che type() restituirà solo il tipo immediato dell'oggetto, ma non sarà in grado di dirvi dell'ereditarietà dei tipi.

>>> type(b) is Test1
False

Per coprire questo, dovreste usare la funzione isinstance. Questo naturalmente funziona anche per i tipi built-in:

>>> isinstance(b, Test1)
True
>>> isinstance(b, Test2)
True
>>> isinstance(a, Test1)
True
>>> isinstance(a, Test2)
False
>>> isinstance([], list)
True
>>> isinstance({}, dict)
True

isinstance() è di solito il modo preferito per assicurare il tipo di un oggetto perché accetta anche i tipi derivati. Quindi, a meno che non abbiate effettivamente bisogno del tipo di oggetto (per qualsiasi ragione), usare isinstance() è preferibile a type().

Il secondo parametro di isinstance() accetta anche una tupla di tipi, quindi è possibile controllare più tipi contemporaneamente. isinstance restituirà true, se l'oggetto è di uno qualsiasi di questi tipi:

>>> isinstance([], (tuple, list, set))
True
Commentari (16)

Potete farlo usando type():

>>> a = []
>>> type(a)

>>> f = ()
>>> type(f)
Commentari (0)

Potrebbe essere più pitonico usare un blocco try...except. In questo modo, se avete una classe che ciancia come una lista, o ciancia come un dict, si comporterà correttamente indipendentemente da quale sia il suo tipo realmente.

Per chiarire, il metodo preferito per "dire la differenza" tra i tipi di variabili è con qualcosa chiamato duck typing: finché i metodi (e i tipi di ritorno) a cui una variabile risponde sono quelli che la vostra subroutine si aspetta, trattatela come ciò che vi aspettate che sia. Per esempio, se avete una classe che sovraccarica gli operatori di parentesi con getattr e setattr, ma usa qualche strano schema interno, sarebbe appropriato che si comportasse come un dizionario se è quello che sta cercando di emulare.

L'altro problema con il controllo di type(A) is type(B) è che se A è una sottoclasse di B, si valuta a false quando, programmaticamente, si spera che sia true. Se un oggetto è una sottoclasse di una lista, dovrebbe funzionare come una lista: il controllo del tipo come presentato nell'altra risposta lo impedirà. (isinstanza funzionerà, comunque).

Commentari (2)