循环列表的两种方式 - 区别

Posted

技术标签:

【中文标题】循环列表的两种方式 - 区别【英文标题】:two ways of looping over list - difference 【发布时间】:2018-10-22 10:08:24 【问题描述】:

我必须反转列表中长度大于 4 的每个单词。所以我尝试了:

for word in words:
    if len(word) >= 5:
        word = word[::-1]

它没有工作。但是这个:

 for i in range(len(words)):
        if len(words[i]) >= 5:
            words[i] = words[i][::-1]

工作正常。有什么区别?

【问题讨论】:

【参考方案1】:

当您遍历列表时,Python 会为您的变量创建引用(具有相同的 ID)。但是,这些是不可编辑的。例如检查这个:Can't modify list elements in a loop Python

考虑这个希望可以帮助你的例子:

words = ['abcdef','abc']

for ind,i in enumerate(words):
    print('Loop '.format(ind))
    i = i[::-1]
    print('words equal '.format(words))
    words[ind] = words[ind][::-1] 
    print('words equal '.format(words))    
    print()

返回:

Loop 0
words equal ['abcdef', 'abc']   # <--- after changing i (nothing changed)
words equal ['fedcba', 'abc']   # <--- after changing words[ind]

Loop 1
words equal ['fedcba', 'abc']   # <--- after changing i (nothing changed)
words equal ['fedcba', 'cba']   # <--- after changing words[ind]

你的情况

最简单的解决方案是使用列表推导。考虑一下:

rWords = [word[::-1] if len(word) >=5 else word for word in words]

【讨论】:

【参考方案2】:
    word = word[::-1]

word 没有引用到 words[i]。 您可以通过函数式编程来做到这一点。

new_words = list(word[::-1] if len(word) >= 5 else word for word in words)

【讨论】:

【参考方案3】:

要了解这里发生了什么,请比较一个类似示例中发生的情况,我想将任何大于 20 的数字设置为 -1:

numbers = [1, 10, 30, 40, 50]
for number in numbers:
    if number > 20:
        number = -1
print(numbers) # same as before!

为什么不将最后三个数字设置为 -1?因为number 这里是一个值——它在内存中的位置与numbers 数组的内容完全无关。您的示例中的word 完全相同。

在您的循环中,word 绑定到一块新内存,其内容恰好与words 数组的当前条目相同。在您的第一个 sn-p 中定义 word 时,您已经失去了任何方法来操作它来自的数组位置。通过像在第二个 sn-p 中那样遍历索引,您可以在数组中保留一个后门。

这两个参考,

http://foobarnbaz.com/2012/07/08/understanding-python-variables/ 和 https://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/

可能有助于理解以下棘手的问题:如果我们有一个列表列表而不是字符串列表,会发生什么?

listOfLists = [[1], [2, 3], [9, 10, 11], [40, 50, 60, 70]]
for l in listOfLists:
    if len(l) >= 3:
        l[:] = l[::-1] # note that `[:]`!!!
print(listOfLists)

这实际上将反转具有超过 2 个元素的任何子列表。你能明白为什么吗?如果是这样,请收下这颗金星:?!

【讨论】:

【参考方案4】:

原因是当你做第一个时,你只是修改了word变量,你没有修改words列表。但是当您使用第二个示例时,您正在修改它,因为您使用的是words[i] = words[i][::-1]。在此示例中,您正在修改单词列表,因为 words[i] 是修饰符;您正在将列表的元素设置为某些内容。

【讨论】:

以上是关于循环列表的两种方式 - 区别的主要内容,如果未能解决你的问题,请参考以下文章

python 计算等差数列和的两种循环方式

python中字典循环的两种方式

ExtJS 3:创建自定义类的两种方式:有啥区别?

解决循环调用的两种方式

线程实现的两种方式及区别

React的两种方式组件定义的区别[重复]