A partir del 2.6, use abstract base classes.
>>> import collections
>>> isinstance([], collections.Sequence)
True
>>> isinstance(0, collections.Sequence)
False
Además, el ABC se puede personalizar para tener en cuenta las excepciones, como no considerar las secuencias como secuencias.Aquí un ejemplo:
import abc
import collections
class Atomic(object):
__metaclass__ = abc.ABCMeta
@classmethod
def __subclasshook__(cls, other):
return not issubclass(other, collections.Sequence) or NotImplemented
Atomic.register(basestring)
Después del registro de la clase Atómica se puede utilizar con isinstance y issubclass:
assert isinstance("hello", Atomic) == True
Esto sigue siendo mucho mejor que una lista no modificable, porque solo necesita registrar las excepciones a la regla, y los usuarios externos del código pueden registrar las suyas propias.
Nótese que en Python 3 la sintaxis para especificar metaclases cambió y se eliminó el basestring
superclase abstracta, que requiere algo como lo siguiente para ser utilizado en su lugar:
class Atomic(metaclass=abc.ABCMeta):
@classmethod
def __subclasshook__(cls, other):
return not issubclass(other, collections.Sequence) or NotImplemented
Atomic.register(str)
Si se desea, es posible escribir código que es compatible tanto con Python 2.6+ como con 3.x, pero hacerlo requiere una técnica un poco más complicada que crea dinámicamente la clase base abstracta necesaria, evitando así los errores de sintaxis debidos a la diferencia de sintaxis de la metaclase. Esto es esencialmente lo mismo que la función six del módulo six de Benjamin Peterson.
class _AtomicBase(object):
@classmethod
def __subclasshook__(cls, other):
return not issubclass(other, collections.Sequence) or NotImplemented
class Atomic(abc.ABCMeta("NewMeta", (_AtomicBase,), {})):
pass
try:
unicode = unicode
except NameError: # 'unicode' is undefined, assume Python >= 3
Atomic.register(str) # str includes unicode in Py3, make both Atomic
Atomic.register(bytes) # bytes will also be considered Atomic (optional)
else:
# basestring is the abstract superclass of both str and unicode types
Atomic.register(basestring) # make both types of strings Atomic
En versiones antes de 2.6, hay damas de tipo en el módulo operator
.
>>> import operator
>>> operator.isSequenceType([])
True
>>> operator.isSequenceType(0)
False
Tenga en cuenta que un objeto de tipo str también es un tipo de secuencia. –
@pi: correcto, y ese es el verdadero problema aquí. Todas las respuestas "buenas" a continuación no toman eso en cuenta. – noamtm
Hmm. De hecho, diría que fue porque realmente no definiste el problema. Si hubiera dicho cuál era inicialmente la tarea, es posible que haya obtenido respuestas más útiles de inmediato. –