ご存知かもしれませんが、 __getitem__
メソッドを実装するとクラスが反復可能になります :
class IterableDemo:
def __getitem__(self, index):
if index > 3:
raise IndexError
return index
demo = IterableDemo()
print(demo[2]) # 2
print(list(demo)) # [0, 1, 2, 3]
print(hasattr(demo, '__iter__')) # False
ただし、これは正規表現一致オブジェクトには当てはまりません。
>>> import re
>>> match = re.match('(ab)c', 'abc')
>>> match[0]
'abc'
>>> match[1]
'ab'
>>> list(match)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '_sre.SRE_Match' object is not iterable
__iter__
メソッドではこの例外がスローされないことに注意してください。このメソッドは実装されていないためです。
>>> hasattr(match, '__iter__')
False
では、クラスを反復可能にせずに__getitem__
を実装するにはどうすればよいですか?
嘘、ひどい嘘、そしてPythonドキュメンテーション。
[〜#〜] c [〜#〜]で実装されたクラスに___getitem__
_を指定するだけでは、反復可能にはなりません。これは、PyTypeObject
に実際に2の場所があり、ここで___getitem__
_をマップできるためです。 _tp_as_sequence
_ =および _tp_as_mapping
_ 。両方とも___getitem__
_( [1] 、 [2] )のスロットがあります。
_SRE_Match
_ のソースを見ると、_tp_as_sequence
_はNULL
に初期化されていますが、_tp_as_mapping
_は定義されています。
iter()
組み込み関数は、1つの引数で呼び出された場合、次のコードを持つ _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
_スロット(明らかに__SRE_Match
_オブジェクトのNULL
)をチェックします。それに失敗すると、if_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
_は__SRE_Match
_インスタンスに対してNULL
であったため、0が返され、_PyObject_GetIter
_は_TypeError: '_sre.SRE_Match' object is not iterable
_を発生させます。