【问题标题】:How do I operate on the actual object, not a copy, in a python for loop?如何在 python for 循环中对实际对象而不是副本进行操作?
【发布时间】:2009-06-12 18:08:15
【问题描述】:

假设我有一个列表

a = [1,2,3]

我想增加该列表中的每个项目。我想做一些语法上简单的事情

for item in a:
    item += 1

但在该示例中,python 仅使用 item 的值,而不是其实际引用,因此当我完成该循环时,a 仍然返回 [1,2,3] 而不是 [2,3, 4]。我知道我可以做类似的事情

a = map(lambda x:x+1, a)

但这并不真正适合我当前的代码,我不想重写它:-\

【问题讨论】:

  • for 循环确实为您提供了实际的对象,而不是副本。问题是您使用的是数字。与所有 Python 值一样,数字(和字符串)都是对象,但每个文字都指代一个唯一的实例。因此,如果您可以将表示 1 的实例修改为 2,您最终会将所有 1 更改为 2,这有点糟糕。另一种方法是为每个值设置一个实例是不可行的。尝试使用 id 函数:id(1)、id('hello world') 等(它总是为相同的文字返回相同的地址。)

标签: python


【解决方案1】:

来吧:

# Your for loop should be rewritten as follows:
for index in xrange(len(a)):
    a[index] += 1

顺便说一句,item 是对a 中的item 的引用,但当然您不能为整数分配新值。对于任何可变类型,您的代码都可以正常工作:

>>> a = [[1], [2], [3], [4]]
>>> for item in a: item += [1]
>>> a
[[1,1], [2,1], [3,1], [4,1]]

【讨论】:

    【解决方案2】:

    在 Python 中,整数(以及浮点数、字符串和元组)是不可变的,因此您拥有的是实际对象(而不是副本),您无法更改它。

    发生的情况是,在item += 1 行中,您正在创建一个新整数(值为item + 1)并将名称item 绑定到它。

    您想要做的是更改a[index] 指向的整数,这就是a[index] += 1 行工作的原因。您仍在创建一个新整数,但随后您将更新列表以指向它。

    附注:

    for index,item  in enumerate(a):
        a[index] = item + 1
    

    ... 比 Triptych 发布的答案更惯用。

    【讨论】:

    • 我开始输入 enumerate 并且不记得为什么我现在改变了 - 哈哈。我想我想坚持任何新手程序员都可能知道的功能,所以我从 enumerate 转到 range(len()),然后决定我不想鼓励 range() 偷偷摸摸地使用内存,所以我改变了到 xrange()。我并不总是确定何时是鼓励最佳实践的好时机 - 有时我认为用户目前愿意理解的只是更好的实践。
    • @Triptych:我认为对于初学者来说坚持最基本的功能是个好主意,但我不同意引入 xrange 很重要。它看起来至少和 enumerate 一样奇怪,并且文档说 xrange 的好处是微乎其微的,除非在病理情况下。 (这也是我的经验。)并且 xrange 在 3.x 中已经拼写为 range。
    【解决方案3】:

    这里有一个基于列表理解的解决方案,而不是基于 map 的解决方案

    a = [item + 1 for item in a]
    

    【讨论】:

      猜你喜欢
      • 2017-03-27
      • 2019-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-28
      • 2018-08-07
      • 1970-01-01
      相关资源
      最近更新 更多