2010-10-04 20 views
6

Vorrei eseguire un'operazione su un argomento basato sul fatto che potrebbe essere un oggetto simile a una mappa o un oggetto simile a una sequenza. Capisco che nessuna strategia sarà affidabile al 100% per il controllo di tipo, ma sto cercando una soluzione robusta.Come distinguere tra una sequenza e una mappatura

Sulla base di questo answer, so come determinare se qualcosa è una sequenza e posso eseguire questo controllo dopo aver controllato se l'oggetto è una mappa.

def ismap(arg): 
    # How to implement this? 

def isseq(arg): 
    return hasattr(arg,"__iter__") 

def operation(arg): 
    if ismap(arg): 
     # Do something with a dict-like object 
    elif isseq(arg): 
     # Do something with a sequence-like object 
    else: 
     # Do something else 

Perché una sequenza può essere vista come una mappa in cui chiavi sono interi, devo solo cercare di trovare una chiave che non è un intero? O forse potrei guardare la rappresentazione delle stringhe? o...?

UPDATE

ho scelto la risposta di SilentGhost perché sembra la più "corretto", ma per le mie esigenze, ecco la soluzione ho finito per applicazione:

if hasattr(arg, 'keys') and hasattr(arg, '__getitem__'): 
    # Do something with a map 
elif hasattr(arg, '__iter__'): 
    # Do something with a sequence/iterable 
else: 
    # Do something else 

In sostanza, ho non voglio fare affidamento su un ABC perché ci sono molte classi personalizzate che si comportano come sequenze e dizionari ma che non estendono ancora le collezioni Python ABC (vedi commento @Manoj). Ho pensato che l'attributo delle chiavi (menzionato da qualcuno che ha rimosso la sua/la sua risposta) era un controllo abbastanza buono per i mapping.

Le classi che estendono la sequenza e la mappatura degli ABC funzionano anche con questa soluzione.

+0

Perché non provare qualcosa di simile sequenza o una mappa simile, e sulla base degli errori, è possibile determinare quali di trattarlo come. – PyRulez

risposta

10
>>> from collections import Mapping, Sequence 
>>> isinstance('ac', Sequence) 
True 
>>> isinstance('ac', Mapping) 
False 
>>> isinstance({3:42}, Mapping) 
True 
>>> isinstance({3:42}, Sequence) 
False 

collections abstract base classes (ABCs)

+3

Come su classi personalizzate? Ad es. 'QuerySet' di Django? Si comporta come una sequenza ma 'isinstance (a_queryset, Sequence)' restituisce 'False'. –

+1

@Manoj: potrebbero aver bisogno di correggere l'ereditarietà? In che senso "si comporta come una sequenza"? – SilentGhost

+1

@SilentGhost: Hmmm. Hai ragione. Immagino che i progettisti dovranno iniziare sottoclasse il tipo appropriato se si aspettano tali operazioni. –

1

Le sequenze hanno un metodo __add__ che implementa l'operatore +. Le mappe non hanno questo metodo, dal momento che aggiungere a una mappa richiede sia una chiave che un valore, e l'operatore + ha solo un lato destro.

Così si può provare:

def ismap(arg): 
    return isseq(arg) and not hasattr(arg, "__add__") 
Problemi correlati