简体   繁体   English

Python:在循环内更改迭代变量是否安全?

[英]Python: Is it safe to change iteration variable inside the loop?

Is it guaranteed that the iteration variable will always follow the original sequence no matter how you modify the variable itself? 是否保证无论您如何修改变量本身,迭代变量都将始终遵循原始顺序?

The doc doesn't mention anything about this. 文档没有提及任何内容。

I've seen similar questions elsewhere but none of them gives authoritative answers. 我在其他地方也看到过类似的问题,但没有一个给出权威性的答案。 I've tested 100 times and it worked 100 times but I'm still not sure whether this is guaranteed. 我已经测试了100次,并且工作了100次,但是我仍然不确定是否可以保证。 So please give some references . 所以请给一些参考

Yes. 是。 It's totally safe to assign to the loop variable(s) in a for loop. for循环中分配循环变量是完全安全的。

From The for statement docs: for语句文档:

The for-loop makes assignments to the variables(s) in the target list. for循环对目标列表中的变量进行赋值。 This overwrites all previous assignments to those variables including those made in the suite of the for-loop: 这将覆盖所有先前对这些变量的分配,包括在for循环套件中进行的分配:

 for i in range(10): print(i) i = 5 # this will not affect the for-loop # because i will be overwritten with the next # index in the range 

This information is also available via help('for') 也可以通过help('for')获得此信息

I agree with PM 2Ring's answer, but you ask if it is guaranteed the loop will "follow the original sequence". 我同意PM 2Ring的回答,但是您问是否可以确保循环将“遵循原始顺序”。 For an iterator defined by a generator function, this cannot be guaranteed, because the sequence may be altered in between iterations; 对于由生成器函数定义的迭代器,这是不能保证的,因为在两次迭代之间可能会更改顺序。 and it is possible to alter the way a generator works by altering a mutable element in the sequence. 并且可以通过更改序列中的可变元素来更改生成器的工作方式。

For example: 例如:

def strange_iter():
    x = {'value': 1}
    while x['value'] < 30:
        x = {'value': x['value'] + 1}
        yield x

for d in strange_iter():
    print(d['value'])
    if d['value'] == 10:
        d['value'] = 15     # loop will skip from 10 to 16

I'm not sure if such generators would have any use in practice or are best considered a bad practice to be avoided. 我不确定这种发电机在实践中是否会有用,还是最好避免使用这种不良做法。

The loop will use the original sequence, for example: 循环将使用原始序列,例如:

a = [1, 2,3 ]
for index,number in enumerate(a):
    print(a[index])
    index = 0
    number = 0

Output: 输出:

1
2
3

I think the syntax 我认为语法

for item in stuff:
    ...

creates an iterator by calling iter(stuff) , then values are extracted by calling next() on that iterator. 通过调用iter(stuff)创建一个迭代器,然后通过对该迭代器调用next()来提取值。

Short answer, It depends.... 简短的回答,这取决于...。

It depends on what you meant by safe . 这取决于您所指的safe Technically there is nothing wrong modifying the variable used for iteration. 从技术上讲,修改用于迭代的变量没有错。 When you iterate over a list or something, you're actually iterating over an iterator. 当您遍历列表或其他内容时,实际上是在遍历迭代器。 It returns the value contained in the container (list, dict whatever)... 它返回包含在容器中的值(列表,字典等)。

If you modify the variable returned by the iterator, you have to keep in mind about the mutability of the object you're trying to modify. 如果修改迭代器返回的变量,则必须牢记要修改的对象的可变性。

If you iterate over integers or strings, you're not actually modifying the variable but affecting a new value to the variable name.. Thus, you're not modifying the value contained in the container. 如果迭代整数或字符串,则实际上并没有修改variable而是影响了变量名的新值。因此,您没有修改容器中包含的值。

But if you're iterating over a container with mutable objects (let say dicts).. Modifying the variable by changing the content, will have an effect on the value contained in the container since they are the same values. 但是,如果您要在具有可变对象的容器上进行迭代(请说辞典)。通过更改内容来修改变量,将对容器中包含的值产生影响,因为它们是相同的值。

But doing something like this would have no effect at all on the value in the container as you're not modifying the value pointed by the variable name but changing to which value the variable name points to: 但是,执行以下操作对容器中的值完全没有影响,因为您没有修改变量名所指向的值,而是更改了变量名所指向的值:

a = [{}, {}, {}]
for x in a:
    x = {'val': x}

While this will: 虽然这将:

a = [{}, {}, {}]
for x in a:
    x['v'] = 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM