可迭代和可订阅有什么区别?是否有任何对象仅属于这些对象类型中的一种?

What is the difference between iterable and Subscriptable? Are there any objects which fall into just one of these object types?

可订阅和可迭代 对象之间的区别是什么? 什么是可订阅但不可迭代的对象,反之亦然?

P.s。可订阅的是其中包含其他对象的对象,迭代器是可订阅的,可以迭代。但我能想到的也仅此而已。

正如@juanpa.arrivillaga 在他的评论中所说:

Subscriptable objects are objects that implement __getitem__. Iterable objects implement __iter__

所以在语言层面这些概念并不直接相关

话虽如此,最常见的 容器 如列表或字典都是可迭代和可订阅的。但是 set 是可迭代且不可订阅的容器的示例,同样,生成器生成可迭代且不可订阅的对象。

我没有可剥离但不可迭代对象的通用示例,但很容易想象一个特殊的 class 可以验证它。极端情况是,如果下标可以是整数,则该对象将不是真正的可迭代对象(不能在其上使用 iter),但 for ... in ... 仍然可以通过在引擎盖下恢复调用 __getitem__ 连续整数

但这是一个可能的例子(即使我无法想象一个真实世界的用例):

class SubscriptNonIter:
    def __init__(self, count):
        self._count = count
        
    def __getitem__(self, key):
        return ''.join(c for i, c in enumerate(key) if i % self._count == 0)

用法示例:

>>> x = SubscriptNonIter(2)
>>> x['abcd']
'ac'
>>> for i in x:
    print(i)

    
Traceback (most recent call last):
  File "...", line 1, in <module>
    for i in x:
  File "...", line 6, in __getitem__
    return ''.join(c for i, c in enumerate(key) if i % self._count == 0)
TypeError: 'int' object is not iterable

What is the difference between subscriptable and iterable objects ?

  • 可订阅对象实现 __getitem__ 并因此计算 obj[key] 语法。

  • 可迭代对象实现 __iter__,因此支持迭代。

What are the objects which are subscriptable but not iterable

一个例子是 re.match(),其中 returns 一个不可迭代的可订阅对象。

import re
m = re.match(r"\w+ (\w+)", "Isaac Newton, physicist")

然后你可以做:

print(m[1])  # "Newton"

但这会产生异常:

for word in m:  # TypeError: 're.Match' object is not iterable
    print(word)

and vice versa?

一个例子是set,它支持迭代但不支持订阅。所以你可以做:

for x in set([42]):
    print(x)  # 42

...但这会产生错误:

set([42])[0]  # TypeError: 'set' object is not subscriptable