删除执行中迭代器的域是否安全(记录的行为?)

发布于 2024-09-04 19:41:44 字数 1087 浏览 3 评论 0原文

我想知道删除 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中做这样的事情安全吗(记录的行为?)?

I wanted to know if is safe ( documented behaviour? ) to delete the domain space of an iterator in execution in Python.

Consider the code:

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' is what I call 'the domain space of an iterator' ( if there is a more appropriate word/phrase, lemme know ).

What I am doing is deleting values from it while the iterator 'dx' is running through it.

Here is what I expect from the code :

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 )

.. and here is what I get:

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

As you can see - what I expect is what I get - which is contrary to the behaviour I have had from other languages in such a scenario.

Hence - I wanted to ask you if there is some rule like "the iterator becomes invalid if you mutate its space during iteration" in Python?

Is it safe ( documented behaviour? ) in Python to do stuff like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌伤浅笑 2024-09-11 19:41:44

来自Python 教程

修改序列不安全
在循环中迭代(这
只能发生在可变序列上
类型,例如列表)。如果您需要
修改您正在迭代的列表
(例如,要复制选定的
items)你必须迭代一个副本。
切片符号使得这个
特别方便:

<前><代码>>>> for x in a[:]: # 制作整个列表的切片副本
...如果 len(x) > 6: a.insert(0, x)
...
>>>>>一个
['射窗','猫','窗户','射窗']

From the Python tutorial:

It is not safe to modify the sequence
being iterated over in the loop (this
can only happen for mutable sequence
types, such as lists). If you need to
modify the list you are iterating over
(for example, to duplicate selected
items) you must iterate over a copy.
The slice notation makes this
particularly convenient:

>>> 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']
醉生梦死 2024-09-11 19:41:44

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

你的例子中发生的事情是

# 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]

Generally speaking no, it's not safe and you may get unpredictable behaviour. Iterators aren't required to behave in an specific way under these circumstances.

What's happening in your example is

# 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]
〃温暖了心ぐ 2024-09-11 19:41:44

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

>>> 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

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

What do you mean by safe? Your code happens not to raise any errors, but it is a distinct possibility of course, consider this:

>>> 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

It is not clear why would you want to do this, but there is no additional rules applicable to iterators. They're acting exactly as any other type would.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文