Comprobación de tipo: un tipo iterable que no es una cadena

Para explicar mejor, considere esta simple función de comprobación de tipos:

from collections import Iterable def typecheck(obj): return not isinstance(obj, str) and isinstance(obj, Iterable) 

Si obj es un tipo iterable distinto de str , devuelve True . Sin embargo, si obj es un tipo str o no iterable, devuelve False .

¿Hay alguna manera de realizar la comprobación de tipo de manera más eficiente? Quiero decir, parece un poco redundante comprobar el tipo de obj una vez para ver si no es un str y luego verificarlo nuevamente para ver si es iterable.

Pensé en enumerar todos los demás tipos iterables además de str como este:

 return isinstance(obj, (list, tuple, dict,...)) 

Pero el problema es que ese enfoque omitirá cualquier otro tipo iterable que no esté explícitamente en la lista.

Entonces … ¿hay algo mejor o el enfoque que di en la función es el más eficiente?

En Python 2.x , la comprobación del atributo __iter__ fue útil (aunque no siempre es acertada), ya que iterables debería tener este atributo, pero las cadenas no.

 def typecheck(obj): return hasattr(myObj, '__iter__') 

El __iter__ fue que __iter__ no era una forma verdaderamente pythonica de hacerlo: algunos objetos podrían implementar __getitem__ pero no __iter__ por ejemplo.

En Python 3.x , las cadenas obtuvieron el atributo __iter__ , rompiendo este método.

El método que enumeró es la forma verdaderamente eficiente más python que conozco en Python 3.x:

 def typecheck(obj): return not isinstance(obj, str) and isinstance(obj, Iterable) 

Hay una forma mucho más rápida (más eficiente), que es marcar __iter__ como en Python 2.x, y luego verificar str .

 def typecheck(obj): return hasattr(obj, '__iter__') and not isinstance(obj, str) 

Esto tiene la misma advertencia que en Python 2.x, pero es mucho más rápido.

Lo compruebo con este código y funciona bien con Python 2 y 3

 from __future__ import unicode_literals import types import collections var = ["a", "b", "c"] if isinstance(var, collections.Iterable) and \ not isinstance(var, types.StringTypes): return var