Python controlla se c'è qualche tipo nell'elenco?


90

Come faccio pitonicamente:

var = 7.0
var_is_good = isinstance(var, classinfo1) or isinstance(var, classinfo2) or isinstance(var, classinfo3) or ... or  isinstance(var, classinfoN)

Sembra sciocco non posso semplicemente passare in un elenco di classinfo:

var_is_good = isinstanceofany( var, [classinfo1, classinfo2, ... , classinfoN] )

Allora qual è la isinstanceofanyfunzione?


Se aggiunge come un numero, sottrae come un numero, moltiplica come un numero ... perché hai bisogno di sapere se è un numero? Vedere la digitazione a papera per maggiori dettagli.
Makoto

Il mio caso d'uso particolare è avere una funzione che restituisce a (funzione che restituisce (o un numberOR restituisce un'espressione sympy)). Voglio controllare che la funzione che ho generato faccia quello che dovrebbe fare quando la passo ad altre funzioni.
D Adams

Perché la tua funzione non restituisce qualcosa di omogeneo? Ecco cos'è l'odore qui; puoi muoverti velocemente con la digitazione a papera, ma dovresti essere coerente in ciò che restituisci.
Makoto

Immagino di poter sempre restituire un'espressione sympy che a volte restituisce un numero e talvolta contiene variabili al suo interno.
D Adams

Questo è quello che penso che tu voglia fare qui; invece di restituire più tipi diversi, restituisci l'unico tipo e, se necessario, riducilo a un numero.
Makoto

Risposte:


200

isinstance()accetta una tupla di classi per il secondo argomento. Restituirà vero se il primo argomento è un'istanza di uno dei tipi in quella sequenza:

isinstance(var, (classinfo1, classinfo2, classinfo3))

In altre parole, offre isinstance() già questa funzionalità, fuori dagli schemi.

Dalla isinstance()documentazione :

Se classinfo non è né un oggetto di classe né un oggetto di tipo, può essere una tupla di oggetti di tipo o classe, oppure può contenere ricorsivamente altre tuple simili (altri tipi di sequenza non sono accettati).

Enfasi mia; notare la natura ricorsiva; (classinfo1, (classinfo2, classinfo3))è anche un'opzione valida.


12

Eri già abbastanza vicino al titolo della tua domanda. Potresti usare anye un elenco:

var = 7.0
var_is_good = any([isinstance(var, classinfo1),
                   isinstance(var, classinfo2),
                   isinstance(var, classinfo3), ...
                   isinstance(var, classinfoN)])

Ma guardando nei documenti di isinstancerivela:

Restituisce vero se l'argomento dell'oggetto è un'istanza dell'argomento classinfo o di una sua sottoclasse (diretta, indiretta o virtuale). Se oggetto non è un oggetto del tipo dato, la funzione restituisce sempre false. Se classinfo non è una classe (oggetto di tipo), può essere una tupla di oggetti di tipo , o può contenere ricorsivamente altre tuple di questo tipo (altri tipi di sequenza non sono accettati). Se classinfo non è un tipo o una tupla di tipi e tali tuple, viene sollevata un'eccezione TypeError.

Ciò significa che il modo migliore per farlo è

var = 7.0
var_is_good = isinstance(var, (classinfo1,
                               classinfo2,
                               classinfo3,
                               ...,
                               classinfoN))

2
Ripetere isinstancesolo il classinfocambiamento non mi sembra molto pitonico.
Makoto

1
Prova var.__class__. E 'questo quello che vuoi? @ Makoto: sono d'accordo. Per niente pitonico!
flamenco

@Makoto Yup. Ma quello era qualcosa che D Adams avrebbe probabilmente potuto facilmente trovare cercando nei documenti "qualsiasi". Ho ampliato la mia risposta alla versione migliore ... ma ovviamente Martijn Pieters è stato più veloce ... ancora una volta.
Martin Thoma

3
any()con una lista è .. inutile. Usa un'espressione generatrice se devi usare any(), almeno ottieni il vantaggio dell'uscita anticipata.
Martijn Pieters

Penso che la isinstancetupla with sia la strada da percorrere. Volevo solo menzionare la soluzione con anycome sembrava essere ciò che sta chiedendo nel titolo.
Martin Thoma

4

Questo risolverà il tuo problema:

valid_instance_types = <tuple of types you want to allow>
var_is_good = isinstance(var, valid_instance_types)

In base alla documentazione, ci sono molti modi in cui puoi passare i valori dei tipi isinstance.

Potresti anche sembrare voluttuoso se stai cercando di fare una convalida più complicata di cui questa è solo una parte.


isinstance () offre già questa funzionalità, passa una tupla con tutti i tipi richiesti da verificare come secondo argomento
RFV

@ RFV5s Sì .... questo è ciò che mostra l'esempio che ho fornito qui. Qual è la tua obiezione?
Nathaniel Ford

1

Generalmente non dovresti usare isinstance, ma quello che vuoi fare può essere realizzato con la funzione incorporata any () .

var_is_good = any(isinstance(var, t) for t in [type1, type2, type3])

7
Questo è eccessivo; isinstance()offre la funzionalità fuori dalla scatola senza utilizzare any().
Martijn Pieters

@MartijnPieters Non mi ero reso conto che isinstance può assumere più tipi, ma sento che la risposta è ancora buona perché la domanda può essere interpretata in senso più ampio come "Come posso verificare se uno qualsiasi dei valori restituiti da una particolare funzione con parametri diversi è vero "
Chad S.

Che tu debba usare o meno isinstance()è irrilevante.
RFV

@ChadS. Vorrei chiederti perché pensi che non dovrebbe usare isinstance()? Grazie.
idature

Perché python evita il controllo del tipo. È un sacco di codice extra (e cicli di CPU) per pochi vantaggi. È preferibile la digitazione a papera.
Ciad S.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.