Начиная с версии 2.6, используйте абстрактные базовые классы .
>>> import collections
>>> isinstance([], collections.Sequence)
True
>>> isinstance(0, collections.Sequence)
False
Кроме того, ABC можно настроить для учета исключений, например, не считая строки последовательностями. Вот пример:
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)
После регистрации класс Atomic может использоваться с isinstance и issubclass :
assert isinstance("hello", Atomic) == True
Это все же намного лучше, чем жестко закодированный список, потому что вам нужно только зарегистрировать исключения из правила, а внешние пользователи кода могут зарегистрировать свои собственные.
Обратите внимание, что в Python 3 синтаксис для указания метаклассов изменился, и абстрактный суперкласс basestring
был удален, для чего требуется использовать что-то вроде следующего:
class Atomic(metaclass=abc.ABCMeta):
@classmethod
def __subclasshook__(cls, other):
return not issubclass(other, collections.Sequence) or NotImplemented
Atomic.register(str)
При желании можно написать код, который совместим как с Python 2.6+ , так и 3.x, но для этого требуется использование немного более сложной техники, которая динамически создает необходимый абстрактный базовый класс, тем самым избежать синтаксических ошибок из-за разницы в синтаксисе метакласса. По сути, это то же самое, что и функция Бенджамина Петерсона шесть модуля with_metaclass()
.
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
В версиях до 2.6 в модуле operator
есть средства проверки типов.
>>> import operator
>>> operator.isSequenceType([])
True
>>> operator.isSequenceType(0)
False