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 の両方と互換性のあるコードを作成することもできますが、そのためには、必要な抽象基本クラスを動的に作成するやや複雑な手法を使用する必要があり、それによってメタクラスの構文の違いによる構文エラーを回避できます。 . これは本質的に、Benjamin Peterson のsixモジュールの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
operator
2.6 より前のバージョンでは、モジュールに型チェッカーがあります。
>>> import operator
>>> operator.isSequenceType([])
True
>>> operator.isSequenceType(0)
False