在为其分配新值时迭代列表

时间:2016-07-19 22:36:33

标签: python for-loop

我有一个python代码,可以在迭代时更改列表。为什么要迭代5次?我希望它应该根据新列表进行迭代。

什么是" for i in l"在底下做什么?为什么迭代时它与l无关?

如果l未更改,为什么在循环后它为空?

cnt = 4
def print_list():
    global cnt
    l=[1, 2, 3, 4, 5]
    for i in l:  # why it iterates 5 times? 
        print "iteration ", i 
        l = range(1, cnt)  # new assignment
        print l 
        cnt-=1
    print "after loop l is ", l # after loop, l is empty

打印结果:

iteration  1
[1, 2, 3]
iteration  2
[1, 2]
iteration  3
[1]
iteration  4
[]
iteration  5
[]
after loop l is []   
编辑:从下面的答案中,我明白了:

  1. 在python中,l指的是赋值后的另一个对象;
  2. 最初由l引用的原始对象不会更改。

2 个答案:

答案 0 :(得分:1)

在for循环中,您将l的变量重新分配给新列表 - 但更改您仍在迭代的原始l

以下是一个更简洁的示例,演示了这种情况,其中l现在称为my_objectmy_objectlist开头,并被重新分配为无意义不影响迭代的字符串:

random_things = [
    "dog", "cat", "fish", "bird", "bug"
]

my_object = xrange(len(random_things))
orig_id = id(my_object)
for i in my_object:
    if i == 0:
        first_iter_id = id(my_object)
    print orig_id == id(my_object),

    # At this point, my_object is
    # reassigned and has no influence on
    # the my_object that is be iterated over
    my_object = random_things[i]
    print i, my_object

print "Original ID == FirstIter ID? {0}".format(orig_id == first_iter_id)
print "Original ID == LastIter ID? {0}".format(orig_id == id(my_object))

<强>输出:

True 0 dog
False 1 cat
False 2 fish
False 3 bird
False 4 bug
Original ID == FirstIter ID? True
Original ID == LastIter ID? False

在此示例中,您可以看到第一次迭代的id my_object如何仍然等于id的原始my_object;但之后,你重新分配my_object,它会在内存中引用一个新对象。

仅仅因为我们将my_object的名称重新分配给内存中的新对象并不意味着我们改变了我们仍在迭代的原始对象的值。

要看到这一点,请注意循环完成后first_iter_id如何等于orig_id - 这是因为在我们在第一次迭代中覆盖first_iter_id之前已分配my_object

答案 1 :(得分:1)

您实际上并未通过分配

来更改列表
l = range(1, cnt)

如果您之前学过C类型语言,则此赋值的行为与另一个范围中的另一个定义相似。此外,列表在for循环开始运行之前被缓存,以避免重复。例如,

for i in range(10):
    #pass

不会创建十次range(10)列表。存储第一个,以便在整个迭代过程中使用它。

如果您真的想要更改列表,则必须执行不在内存中创建新列表的操作。如,

l.append()
l.remove()
l.pop()
l[x] = y

你可以自己在循环中尝试这些并找出结果。