2010-10-04 22 views
6

Me gustaría realizar una operación en un argumento basado en el hecho de que podría ser un objeto similar a un mapa o un objeto similar a una secuencia. Entiendo que ninguna estrategia va a ser 100% confiable para el tipo de verificación, pero estoy buscando una solución robusta.Cómo distinguir entre una secuencia y un mapeo

Basado en este answer, sé cómo determinar si algo es una secuencia y puedo hacer esta comprobación después de comprobar si el objeto es un mapa.

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 

Debido a que una secuencia puede ser visto como un mapa donde las claves son números enteros, ¿debo tratar de encontrar una llave que no es un entero? ¿O tal vez podría mirar la representación de la cadena? o...?

ACTUALIZACIÓN

He escogido la respuesta de SilentGhost porque se ve como el más "correcta", pero para mis necesidades, aquí está la solución que terminé de aplicación:

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 

Esencialmente, No quiero depender de un ABC porque hay muchas clases personalizadas que se comportan como secuencias y diccionarios, pero que aún no amplían el ABC de las colecciones de Python (vea el comentario de @Manoj). Pensé que el atributo de las teclas (mencionado por alguien que eliminó su respuesta) era un cheque suficientemente bueno para las asignaciones.

Las clases que amplían la Secuencia y la Cartografía ABC funcionarán también con esta solución.

+0

¿Por qué no intentar algo así como la secuencia o mapa como, y sobre la base de los errores, puede determinar qué tratan como. – PyRulez

Respuesta

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

¿Qué tal las clases personalizadas? Por ej. ¿'QuerySet' de Django? Se comporta como una secuencia, pero 'isinstance (a_queryset, Sequence)' devuelve 'False'. –

+1

@Manoj: ¿podrían necesitar arreglar la herencia? ¿En qué sentido "se comporta como una secuencia"? – SilentGhost

+1

@SilentGhost: Hmmm. Tienes razón. Supongo que los diseñadores tendrán que comenzar subclasificando el tipo apropiado si esperan tales operaciones. –

1

Las secuencias tienen un método __add__ que implementa el operador +. Los mapas no tienen ese método, ya que agregarlo a un mapa requiere una clave y un valor, y el operador + solo tiene un lado derecho.

por lo que puede probar:

def ismap(arg): 
    return isseq(arg) and not hasattr(arg, "__add__") 
Cuestiones relacionadas