2013-08-28 22 views
9

Come verificare se un oggetto è un elenco di stringhe? ho potuto verificare solo se un oggetto è stringa come tale:Come verificare se un oggetto è un elenco di stringhe?

def checktype(obj): 
    if isinstance(obj,str): 
    print "It's a string" 

obj1 = ['foo','bar','bar','black','sheet'] 
obj2 = [1,2,3,4,5,'bar'] 
obj3 = 'bar' 

for i in [obj1,obj2,obj3]: 
    checktype(i) 

output desiderato:

It's a list of strings 
It's not a list of strings or a single string 
It's a single string 
+2

Per chiarezza vorrei rinominare 'checktype' a' is_list_of_string'. –

+3

Un caso limite da considerare: '' [] 'un elenco di stringhe o no? – abarnert

+0

nope '[]' non sarebbe una lista di stringhe, è una lista vuota. – alvas

risposta

15

Qualcosa di simile, presumo? Potresti fare alcuni controlli per vedere se si tratta di una singola stringa.

>>> def checktype(obj): 
     return bool(obj) and all(isinstance(elem, basestring) for elem in obj) 

>>> obj1 = ['foo','bar','bar','black','sheet'] 
>>> obj2 = [1,2,3,4,5,'bar'] 
>>> obj3 = 'bar' 
>>> for i in [obj1, obj2, obj3] : 
     print checktype(i) 


True 
False 
True 

Perché controllare per basestring invece di str?

Si dovrebbe controllare per basestring invece di str dal momento che è una classe comune da cui entrambi i tipi str e unicode ereditano da. Il controllo solo dello str esclude i tipi unicode.

Come da Steven Rumbalski's suggerimenti, se è necessario controllare in modo specifico un elenco di stringhe, è possibile farlo.

>>> def is_list_of_strings(lst): 
     return bool(lst) and not isinstance(lst, basestring) and all(isinstance(elem, basestring) for elem in lst) 
     # You could break it down into `if-else` constructs to make it clearer to read. 

>>> for i in [obj1, obj2, obj3] : 
     print is_list_of_strings(i) 


True 
False 
False 

EDIT - Come da abarnert's suggerimento, si potrebbe anche verificare la presenza di un list invece di not isinstance(lst, basestring), il codice sarebbe ottenere riscritto come.

>>> def is_list_of_strings(lst): 
     return bool(lst) and isinstance(lst, list) and all(isinstance(elem, basestring) for elem in lst) 
     # You could break it down into `if-else` constructs to make it clearer to read. 

>>> for i in [obj1, obj2, obj3] : 
     print is_list_of_strings(i) 


True 
False 
False 

Allontanandoci da una fodera, potremmo usare.

>>> def is_list_of_strings(lst): 
     if lst and isinstance(lst, list): 
      return all(isinstance(elem, basestring) for elem in lst) 
     else: 
      return False 
+3

La specifica dice di testare un * list * di stringhe, quindi 'checktype ('bar')' dovrebbe restituire 'False'. Buon lavoro usando 'basestring'. –

+0

@StevenRumbalski: risolto. Grazie per il commento. :) –

+3

In realtà, penso che sarebbe meglio controllare 'isinstance (lst, list)' di 'not isinstance (lst, basestring)'. Dopotutto, una stringa di mappatura dict alle stringhe non è una lista di stringhe più di una stringa ... Ma in caso contrario, ottima risposta. – abarnert

13

per verificare se tutti gli elementi di un elenco sono stringhe, utilizzare il all incorporato e un generatore:

if all(isinstance(s, str) for s in lis): 

Nota però che, se l'elenco è vuoto, questo sarà ancora tornare True dato che questo è tecnicamente un elenco di 0 stringhe. Tuttavia, dal momento che si vuole considerare [] come False, avrete bisogno di fare questo:

if lis and all(isinstance(s, str) for s in lis): 

Così, la vostra funzione dovrebbe essere qualcosa di simile:

def checktype(obj): 
    # This if statement makes sure input is a list that is not empty 
    if obj and isinstance(obj, list): 
     return all(isinstance(s, str) for s in obj) 
    else: 
     return False 

Questa funzione restituisce solo True se il suo input è una lista che non è vuota e che è composta interamente da stringhe. Qualsiasi altra cosa (come [], ['a', 1], ('a', 'b'), ecc.) Renderà il reso False.

Inoltre, l'utilizzo di all in questo modo ha un ulteriore vantaggio in quanto smette di controllare il primo elemento rilevato che restituisce False (non è una stringa). Ciò consente di lavorare con elenchi molto grandi in modo abbastanza efficiente.

+2

Buona risposta, ma cambiare il controllo dell'istanza da 'str' a' basestr'. –

+2

... a meno che, ovviamente, l'OP non significasse veramente "lista di' str' "piuttosto che" lista di stringhe "... che è possibile, ma non ha detto che era ciò che voleva. (@StevenRumbalski lo spiega abbastanza bene nella sua risposta, quindi non penso che sia necessario spiegarlo di nuovo qui.) – abarnert

+0

Bene, sono andato con 'str' perché, nel post dell'OP, stava controllando se era di tipo' str', non 'basestring'. – iCodez

2

Le risposte che ho letto finora alzare exepctions quando dato un non-lista che non è una stringa ... e non è iterabile neanche.Tale questione è affrontata in:

In Python, how do I determine if an object is iterable?

Prendendo l'approccio anatra tipizzazione:

def categorize(x): 
    result = "not a string or list of strings" 
    if isinstance(x, basestring): 
     return "It's a single string" 
    try: 
     if all(isinstance(y, basestring) for y in x): 
      return "It's a list of strings" 
    except TypeError: 
     pass 
    return "It's not a list of strings or a single string" 

data = [ 5, "xyzzy", list("xyzzy"), ['1', '23', 456]] 
for x in data: 
    print x, categorize(x) 

uscita:

5 It's not a list of strings or a single string 
xyzzy It's a single string 
['x', 'y', 'z', 'z', 'y'] It's a list of strings 
['1', '23', 456] It's not a list of strings or a single string 
Problemi correlati