Ответ 1
Абстрактные классы из collections
используйте ABCMeta.register(subclass)
для
Зарегистрировать подкласс как "виртуальный подкласс" этой ABC.
В Python 3 issubclass(bytearray, Sequence)
возвращает True
, потому что bytearray
явно зарегистрирован как подкласс ByteString
(который получен из Sequence
) и MutableSequence
. См. Соответствующую часть Lib/_collections_abc.py:
class ByteString(Sequence):
"""This unifies bytes and bytearray.
XXX Should add all their methods.
"""
__slots__ = ()
ByteString.register(bytes)
ByteString.register(bytearray)
...
MutableSequence.register(bytearray) # Multiply inheriting, see ByteString
Python 2 этого не делает (из Lib/_abcoll.py):
Sequence.register(tuple)
Sequence.register(basestring)
Sequence.register(buffer)
Sequence.register(xrange)
...
MutableSequence.register(list)
Это поведение было изменено в Python 3.0 (в this commit):
Добавьте ABC ByteString, который объединяет байты и bytearray (но не memoryview). Там нет ABC для "объектов API буфера стиля PEP 3118", потому что нет способ распознать их в Python (кроме попытки использовать memoryview() на них).
И еще информация в PEP 3119:
Это предложение добавить поддержку базового класса (ABC) для Python 3000. Он предлагает: [...] Конкретные ABC для контейнеров и итераторов, которые будут добавлены к коллекции.
Значительная часть мышления, внесённого в предложение, касается не специфический механизм ABC, в отличие от интерфейсов или общих Функции (GF), но о разъяснении философских вопросов типа "что делает набор", "что делает отображение" и "что делает последовательность".
[...] метакласса для использования с ABC, что позволит нам добавить ABC как "виртуальный базовый класс" (не та же концепция, что и в С++) в любой класс, в том числе в другую ABC. Это позволяет стандартной библиотеке определять последовательность ABC и MutableSequence и регистрировать их как виртуальные базовые классы для встроенных типов, таких как basestring, tuple и list, так что, например, все условия истинны: [...] issubclass (bytearray, MutableSequence).
Только FYI memoryview
был зарегистрирован как подкласс Sequence
только в Python 3.4:
Там нет привязки для этого из-за смешения последовательности/отображения так что это простая пропущенная явная регистрация.
(подробнее см. issue18690).
PySequence_Check
из API Python C не полагается на модуль collections
:
int
PySequence_Check(PyObject *s)
{
if (PyDict_Check(s))
return 0;
return s != NULL && s->ob_type->tp_as_sequence &&
s->ob_type->tp_as_sequence->sq_item != NULL;
}
Он проверяет ненулевое поле tp_as_sequence
(пример для bytearray
), и если это удастся, для ненулевого sq_item
(в основном это getitem - пример для bytearray
).