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.