类型错误:'zip' 对象不支持下标操作。

96
我有一个以token/tag格式标记的文件,我尝试使用一个函数,返回一个(word,tag)列表中的单词元组。
def text_from_tagged_ngram(ngram): 
    if type(ngram) == tuple:
        return ngram[0]
    return " ".join(zip(*ngram)[0]) # zip(*ngram)[0] returns a tuple with words from a (word,tag) list

在Python 2.7中它工作良好,但在Python 3.4中,在最后一行显示错误,提示“TypeError: 'zip' object is not subscriptable”。为什么它停止工作了?我该如何修复它?

在Python 2到Python 3的过程中,还有其他几件事情以类似的方式发生了变化;请参见如何在Python 3中使用filter、map和reduce

2个回答

163

在Python 2中,zip 返回一个列表。在Python 3中,zip 返回一个可迭代对象。但是你可以通过调用 list 将其转换为列表,例如:

list(zip(...))

在这种情况下,应该是:
list(zip(*ngram))

使用列表,可以使用索引:

items = list(zip(*ngram))
...
items[0]

但如果你只需要第一个元素,那么你不一定需要一个列表。你可以直接使用next函数。

在这种情况下,代码会是这样的:

next(zip(*ngram))

0
在3.x中,zip返回一种特殊类型的迭代器,而不是列表。文档解释道:

zip()是惰性的:元素直到可迭代对象被迭代(例如通过for循环或包装在list中)才会被处理。

这意味着它不能被索引,因此旧代码尝试对zip的结果进行索引或切片将导致TypeError。只需将结果传递给list即可生成一个列表,该列表可以像2.x中那样使用。
这也意味着第二次迭代zip的结果将找不到任何元素。因此,如果需要重复使用数据,请创建一个列表并重复使用该列表 - 再次创建它将生成一个空列表:
>>> example = zip('flying', 'circus')
>>> list(example)
[('f', 'c'), ('l', 'i'), ('y', 'r'), ('i', 'c'), ('n', 'u'), ('g', 's')]
>>> list(example)
[]

这个迭代器是作为一个类的实例实现的...

>>> example = zip('flying', 'circus')
>>> example
<zip object at 0x7f76d8365540>
>>> type(example)
<class 'zip'>
>>> type(zip)
<class 'type'>

...内置的:

>>> class example(int, zip): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: multiple bases have instance lay-out conflict
>>> # and that isn't caused by __slots__ either:
>>> zip.__slots__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'zip' has no attribute '__slots__'

(另请参见:TypeError:多个基类具有实例布局冲突无法继承定义__slots__的多个类?
这样做的关键优势是节省内存,并且在输入也是惰性的情况下允许短路。例如,两个大型输入文本文件的相应行可以一起zip并迭代,而无需将整个文件读入内存:
with open('foo.txt') as f, open('bar.txt') as g:
    for foo_line, bar_line in zip(f, g):
        print(f'{foo_line:.38} {bar_line:.38}')
        if foo_line == bar_line:
            print('^ found the first match ^'.center(78))
            break

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接