Ответ 1
Есть ложь, проклятая ложь, а затем есть документация на Python.
Для __getitem__
для класса, реализованного в C, недостаточно, чтобы он был итерируемым. Это потому, что в PyTypeObject
есть фактически 2 места, где __getitem__
можно сопоставить с: tp_as_sequence
и tp_as_mapping
. Оба имеют слот для __getitem__
([1], [2]).
Рассматривая источник SRE_Match
, tp_as_sequence
инициализируется NULL
тогда как tp_as_mapping
определяется.
Встроенная функция iter()
, если вызывается с одним аргументом, вызовет PyObject_GetIter
, который имеет следующий код:
f = t->tp_iter;
if (f == NULL) {
if (PySequence_Check(o))
return PySeqIter_New(o);
return type_error("'%.200s' object is not iterable", o);
}
Сначала он проверяет слот tp_iter
(очевидно, NULL
для объектов _SRE_Match
); и если это PySequence_Check
, то, если PySequence_Check
вернет true, будет создан новый итератор последовательности, иначе будет создан TypeError
.
PySequenceCheck
сначала проверяет, является ли объект dict
или подклассом dict
и возвращает false в этом случае. В противном случае он возвращает значение
s->ob_type->tp_as_sequence &&
s->ob_type->tp_as_sequence->sq_item != NULL;
и поскольку s->ob_type->tp_as_sequence
был NULL
для экземпляра _SRE_Match
, 0 будет возвращен, а PyObject_GetIter
вызывает TypeError: '_sre.SRE_Match' object is not iterable
.