Python 3.4嵌套循环使用lambda过滤器奇怪地工作

pan*_*mer 2 python lambda loops python-3.x

我正在尝试使用NLTK的文本代码(https://github.com/nltk/nltk/blob/develop/nltk/tokenize/texttiling.py).

它是一个代码,根据文档内容将文档输入分成几个图块.我注意到,通过将整个文本作为一个瓦片返回,平铺对于某些文档根本不起作用,并且发现这部分代码工作很奇怪.

    depth_tuples = sorted(zip(depth_scores, range(len(depth_scores))))
    depth_tuples.reverse()
    hp = filter(lambda x:x[0]>cutoff, depth_tuples)

    for dt in hp:
        boundaries[dt[1]] = 1
        for dt2 in hp: #undo if there is a boundary close already
            if dt[1] != dt2[1] and abs(dt2[1]-dt[1]) < 4 \
                   and boundaries[dt2[1]] == 1:
                boundaries[dt[1]] = 0
    return boundaries
Run Code Online (Sandbox Code Playgroud)

Depth_tuple是一个包含元组列表[(score,index)]的列表,hp是一个过滤结果,其得分大于某个截止值.

使用嵌套循环,它为hp的每个条目分别迭代hp两次.换句话说,对于hp的每个条目,它应检查hp的所有条目的某些内容.但是我注意到在第一次迭代后没有执行第二个循环(对于hp中的dt2).这就像dt2指针在第一个dt的hp末尾到达,并且它没有为新的迭代初始化.

为了给你一个这种现象的简化例子,比如x = [(0.6,3),(0.2,1),(0.5,2),(0.4,3)]

如果截止值为0.3,则hp包含[(0.6,3),(0.5,2),(0.4,3)]

所以循环应该是这样的

当x =(0.6,3)时,第二个循环检查[(0.6,3),(0.5,2),(0.4,3)]

当x =(0.5,2)时,第二个循环再次检查[(0.6,3),(0.5,2),(0.4,3)]

但它只在x =(0.6,3)时才这样做,而对于x的其余部分,第二个循环不会运行.

我最初怀疑迭代器已经在第二个循环中达到了hp的结尾,但它不能解释第一个循环的hp中的迭代器如何仍然可以...

你能解释一下为什么会这样吗?谢谢!

Ant*_*ala 5

您正在使用Python 3,并且该配方是为Python 2编写的.在Python 2中,filter返回a list,显然可以使用for(内部for dt2 in hp)多次迭代.

但是在Python 3中,hp将是一个通过迭代器 ; 现在,外部for将消耗第一个元素,而内部for将消耗所有剩余元素; 当内循环退出时,外循环找到一个空迭代器并退出.

或者,正如Python 2和3文档所述,在Python 2 filter(function, iterable)中等同于列表理解

[item for item in iterable if function(item)]
Run Code Online (Sandbox Code Playgroud)

在Python 3中,它等同于生成器表达式

(item for item in iterable if function(item))
Run Code Online (Sandbox Code Playgroud)

作为最简单的修复,将迭代器返回filterlist:

hp = list(filter(lambda x: x[0] > cutoff, depth_tuples))
Run Code Online (Sandbox Code Playgroud)