【问题标题】:How come regex match objects aren't iterable even though they implement __getitem__?为什么正则表达式匹配对象即使实现了 __getitem__ 也不是可迭代的?
【发布时间】:2019-02-20 18:39:24
【问题描述】:

如您所知,implementing a __getitem__ method makes a class iterable:

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__

【问题讨论】:

  • 我什至无法下标match...
  • @Sweeper Match.__getitem__ 被添加到 Python 3.6 docs.python.org/3/library/re.html#re.Match.__getitem__
  • @DeepSpace 啊...我使用的是 3.5。
  • @PedroLobito 但这没有解释吗?
  • @PedroLobito 这是一个完全不同的问题,不是吗?我的匹配对象确实有一个__getitem__ 方法...

标签: python iterable


【解决方案1】:

有谎言,该死的谎言,还有 Python 文档。

C 中实现的类具有 __getitem__ 不足以使其可迭代。这是因为PyTypeObject 中实际上有 2 个位置,__getitem__ 可以映射到:tp_as_sequencetp_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 对象);如果失败,则 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-&gt;ob_type-&gt;tp_as_sequenceNULL_SRE_Match 实例,因此将返回0,并且PyObject_GetIter 引发TypeError: '_sre.SRE_Match' object is not iterable

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多