4

我想知道在 Python 中删除迭代器的域空间是否安全(记录在案的行为?)。

考虑代码:

import os
import sys

sampleSpace = [ x*x for x in range( 7 ) ]

print sampleSpace

for dx in sampleSpace:

    print str( dx )

    if dx == 1:

        del sampleSpace[ 1 ]
        del sampleSpace[ 3 ]

    elif dx == 25:

        del sampleSpace[ -1 ]

print sampleSpace

“sampleSpace”就是我所说的“迭代器的域空间”(如果有更合适的词/短语,请让我知道)。

我正在做的是在迭代器“dx”运行时从中删除值。

这是我对代码的期望:

Iteration versus element being pointed to (*):

0: [*0, 1, 4, 9, 16, 25, 36]
1: [0, *1, 4, 9, 16, 25, 36] ( delete 2nd and 5th element after this iteration )
2: [0, 4, *9, 25, 36]
3: [0, 4, 9, *25, 36] ( delete -1th element after this iteration )
4: [0, 4, 9, 25*] ( as the iterator points to nothing/end of list, the loop terminates )

..这就是我得到的:

[0, 1, 4, 9, 16, 25, 36]
0
1
9
25
[0, 4, 9, 25]

正如你所看到的——我所期望的就是我得到的——与我在这种情况下从其他语言中得到的行为相反。

因此 - 我想问你是否有一些规则,如“如果你在迭代期间改变它的空间,迭代器将变得无效”在 Python 中?

在 Python 中做这样的事情是否安全(记录在案的行为?)?

4

3 回答 3

6

来自Python 教程

在循环中修改被迭代的序列是不安全的(这只会发生在可变序列类型上,例如列表)。如果您需要修改您正在迭代的列表(例如,复制所选项目),您必须迭代一个副本。切片表示法使这特别方便:

>>> for x in a[:]: # make a slice copy of the entire list
...    if len(x) > 6: a.insert(0, x)
...
>>> a
['defenestrate', 'cat', 'window', 'defenestrate']
于 2010-06-03T11:34:29.167 回答
1

一般来说,不,这不安全,您可能会遇到不可预知的行为。在这些情况下,迭代器不需要以特定方式运行。

您的示例中发生的情况是

# list is [0, 1, 4, 9, 16, 25, 36]

if dx == 1:
    # we're at index 1 when this is true
    del sampleSpace[ 1 ]
    # we've removed the item at index 1, and the iterator will move to the next valid position - still index 1, but in a mutated list. We got lucky in this case
    # the list now contains [0, 4, 9, 16, 25, 36]
    del sampleSpace[ 3 ]   
    # we remove the item at index 3 which is (now) value 16
    # the list now contains [0, 4, 9, 25, 36]
elif dx == 25:

    del sampleSpace[ -1 ]
    # we remove the final item, list now looks like
    # the list now contains [0, 4, 9, 25]
于 2010-06-03T11:34:58.073 回答
0

你说的安全是什么意思?您的代码碰巧不会引发任何错误,但当然这是一种明显的可能性,请考虑这一点:

>>> a = range(3)
>>> for i in a:
    del a


Traceback (most recent call last):
  File "<pyshell#13>", line 2, in <module>
    del a
NameError: name 'a' is not defined
>>> a
[0, 1, 2]
>>> for i in a:
    del a[i+1]


Traceback (most recent call last):
  File "<pyshell#27>", line 2, in <module>
    del a[i+1]
IndexError: list assignment index out of range

目前尚不清楚您为什么要这样做,但没有适用于迭代器的附加规则。他们的行为与任何其他类型的行为完全一样。

于 2010-06-03T11:23:47.820 回答