2010-04-15 20 views
18

Qual è il modo più semplice per verificare se qualcosa è un elenco?Controlla se qualcosa è un elenco

Un metodo doSomething ha i parametri a e b. Nel metodo, eseguirà un ciclo attraverso l'elenco a e farà qualcosa. Mi piacerebbe un modo per assicurarmi che sia list, prima di eseguire il ciclo, evitando così un errore o la sfortunata circostanza di passare una stringa e recuperare una lettera da ciascun ciclo.

Questa domanda deve essere stata posta prima - tuttavia i miei google mi hanno deluso. Saluti.

+7

Penso che il "modo Python" sarebbe semplicemente permettere alle persone di passare qualsiasi cosa. Fidati dei programmatori che usano la tua funzione. –

+7

"evitando così un errore" In che modo il controllo "evita" l'errore? È ancora sbagliato E se qualcuno usasse una tupla o un altro oggetto simile ad una lista che funzioni davvero correttamente? Perché impedir loro di usare una classe di cose simili alle liste che non hai pensato? In che modo questo "evita" l'errore? –

+0

L'unica volta che controllo i tipi di argomenti è se voglio che la mia funzione faccia cose diverse per tipi diversi, per esempio interi o stringhe. Ma anche allora, di solito finisco per refactoring il codice e la rimozione dei controlli di tipo. Al giorno d'oggi, in realtà sono * più * probabile che scriverò codice che solleva "ValueError" o somesuch quando l'input è negativo. A differenza di C++, le eccezioni sono i tuoi amici. –

risposta

13

per abilitare più casi d'uso, ma ancora trattare stringhe come scalari, non verificare la presenza di un essere un elenco, controllare che non è una stringa:

if not isinstance(a, basestring): 
    ... 
+5

+1, mi piace il meglio perché molti non-elenchi vanno bene, le stringhe (semplice e unicode, da cui il 'basestring') sono le pecore nere e dovrebbero essere quelle individuate. –

+1

L'uso di questo codice indica che quasi sicuramente stai facendo qualcosa di sbagliato. Se fornisci un'API coerente, questo non dovrebbe essere necessario. Ciò può anche violare le aspettative degli utenti quando i tipi sono usati come sono intesi, ad esempio quando qualcuno usa un oggetto che è concettualmente una stringa ma è un'istanza di una classe diversa. –

4

Di solito è considerato non un buon stile di eseguire tipo-check in Python, ma provate

if isinstance(a, list): 
    ... 

(penso che si può anche verificare se a.__iter__ esiste.)

+1

Hai ragione, non è un buon stile tipografico. Il controllo di un metodo '__iter__' è altrettanto sciocco: basta fare' per oggetto in a'. Se hai un motivo per sospettare che 'a' non sia iterabile (cattivo, cattivo!), prendi il' TypeError'. –

+0

@Mike: '" 12345 ".__ iter__' -> AttributeError: oggetto 'str' non ha attributo '__iter__', ma 'per x in" 12345 ": stampa x' funziona – kennytm

+1

Quale dovrebbe essere * scoraggiante *, non * incoraggiante *. Il controllo di' __iter__' funziona solo in base ai dettagli dell'implementazione, non a una differenza significativa, e non indica se un oggetto è iterabile o indica qualsiasi metodo diretto le informazioni sulle stringhe. Se un oggetto usa il vecchio protocollo iteratore (chiamando indici sequenziali) o è implementato in C in modo brutto (tale che il metodo '__iter__' non è esposto) come in questo caso, il risultato sembra piuttosto non intuitivo. –

7

I'd like a way to make sure a is a list, before looping through

Documentare la funzione.

+1

Questa soluzione è la più potente, utile e robusta. –

+1

Ha il vantaggio aggiuntivo in cui, se qualcuno ti invia una email e dice "hey, la tua funzione fa qualcosa di strano alle stringhe", sai automaticamente che sono un idiota. Nessun compilatore può farlo. – detly

+1

Ma a volte sai già che sono un idiota, non riesci a sbarazzartene, vuoi che smettano di disturbarti, e ti chiedi se c'è del codice che puoi scrivere per stroncarlo sul nascere. È una vana speranza; ci sono sempre più pazzi creativi. Qui è dove la gente trova idee come i lanciamissili USB. –

9

Typechecking danneggia la generalità, la semplicità e la manutenibilità del codice. È usato raramente in buoni programmi Python idiomatici.

Ci sono due ragioni principali persone vogliono TYPECHECK:

  1. Per emettere errori se il chiamante fornisce il tipo sbagliato.

    Questo non vale la pena. Se l'utente fornisce un tipo incompatibile per l'operazione che si sta eseguendo, verrà generato un errore quando si verifica la compatibilità. È preoccupante che ciò non avvenga immediatamente, ma in genere non richiede molto tempo e produce un codice più robusto, semplice, efficiente e più facile da scrivere.

    Spesso le persone insistono su questo con la speranza che possano prendere tutte le cose stupide che un utente può fare. Se un utente è disposto a fare cose arbitrariamente stupide, non c'è nulla che tu possa fare per fermarlo. Typechecking ha principalmente il potenziale di mantenere un utente che entra con i propri tipi che sostituiscono i rimpiazzi per quelli sostituiti o quando l'utente riconosce che la propria funzione dovrebbe essere effettivamente polimorfica e fornisce qualcosa di diverso che può accettare la stessa operazione.

    Se avessi un grande sistema in cui un sacco di cose fatte da molte persone dovessero combaciare perfettamente, userei un sistema come zope.interface per verificare che tutto combaci perfettamente.

  2. Per fare cose diverse in base al tipo di argomenti ricevuti.

    Ciò rende il codice peggiore perché l'API non è coerente. Una funzione o un metodo dovrebbe fare una cosa, non cose fondamentalmente diverse. Questo finisce per essere una caratteristica che di solito non vale la pena sostenere.

    Uno scenario comune è quello di avere un argomento che può essere un foo o un elenco di foos. Una soluzione più pulita è semplicemente quella di accettare una lista di premi. Il tuo codice è più semplice e più coerente.Se si tratta di un caso d'uso comune importante solo per avere un foo, si può considerare di avere un altro metodo/funzione di convenienza che chiama quello che accetta un elenco di foos e non perde nulla. Fornire la prima API non sarebbe stata solo più complicata e meno coerente, ma si sarebbe interrotta quando i tipi non erano i valori esatti previsti; in Python distinguiamo gli oggetti in base alle loro capacità, non ai loro effettivi tipi. È quasi sempre meglio accettare un iterabile arbitrario o una sequenza invece di una lista e tutto ciò che funziona come un foo invece di richiedere un foo in particolare.

Come si può vedere, non credo che nessuna delle due ragioni sia abbastanza convincente da consentire il controllo del funzionamento in circostanze normali.

Problemi correlati