【问题标题】:List, variable assignment and function in PythonPython中的列表、变量赋值和函数
【发布时间】:2017-11-24 12:55:39
【问题描述】:

我有以下代码:

def proc2(p):
    p=p+[1]
y=[2,5]
proc2(y)
print(y)


z=[2,5]
z=z+[1]
print(z)

代码的输出是:

[2, 5]
[2, 5, 1]

我了解 y 未修改[2,5,1]。但是,y 被重新分配到一个新列表,即[2,5,1],对吗?那为什么 y 仍然引用原始值? 如果 z 的值改变了,为什么 y 不改变?

附:我刚刚问了一个question,和这个几乎一样。该问题已被标记为与另一个问题重复。但是,我认为它们有点不同。这就是为什么我再次发布我的问题。我想我一定错过了一些关于功能的东西。

【问题讨论】:

  • proc2() 中,附加了p 列表,然后将p 重新分配给更长的列表。正如您所提到的,这不会影响仍然指向较短列表的y。但是,在您的第二个示例中,z 实际上被重新分配为指向附加列表。
  • 分配给z的原始列表的值实际上没有改变。您根本不再引用它。如果你做了例如old_z = z 之前 z += 1,然后打印old_z,你会看到的。行为没有区别。
  • p=p+[1] 不会修改 p 之前引用的列表。它修改 变量 p 以引用新列表。另一个变量,仍然引用 old 列表,不会受到影响。
  • @jonrsharpe 你说的,我完全明白了。但是,在运行proc2(y) 之后,y 现在应该指向新列表[2,5,1]。那么为什么当我打印 y 时,python 说 y 仍然指向 [2,5]
  • 因为它仍然引用旧列表?只有局部变量 p 被重新分配。

标签: python python-3.x


【解决方案1】:

y 被重新分配到一个新列表

不,您的代码中只有一个 y = ... 赋值。

当你的函数执行时会发生以下情况:

# implicitly: assign formal parameter name to actual argument value
p = y

# compute p + [1] => [2, 5, 1]
# assign the result to the name p
p = p + [1]

# aaaand... nothing from here on.

因此,您的函数计算一个结果(一个新列表),在函数范围内分配名称 p,然后函数一退出,p 就会丢失。

如果您不想编写一个改变您的输入列表的函数,您需要返回计算值并重新分配名称y 以查看所需的效果。 p>

>>> def proc2(p):
...     p = p + [1]
...     return p
... 
>>> y = [2,5]
>>> y = proc2(y)
>>> y
[2, 5, 1]

请注意,即使您在函数内分配了y = ...,该名称也将是函数的本地名称,而外部作用域不会关心:

>>> def proc2(y):
...     y = y + [1]
... 
>>> y = [2,5]
>>> proc2(y)
>>> y
[2, 5]

最后,你可以告诉 Python 你的意思是你的函数体内的全局y,但这被认为是糟糕的风格(绝对在这里和大多数其他情况下)。

>>> def proc2():
...     global y
...     y = y + [1]
... 
>>> y = [2,5]
>>> proc2()
>>> y
[2, 5, 1]

【讨论】:

  • 我同意你所说的一切,除了“如果你不想编写一个改变你的输入列表的函数”。就像@jonrsharpe 提到的那样,分配给p 的原始列表的值,即输入列表[2, 5],实际上并没有发生突变。只是 p 被重新分配到另一个列表 [2, 5, 1]。你同意吗?
  • @failbetter 我从未声称您的原始函数会改变您的输入列表。我想说你必须返回一个值才能让你的函数做一些有用的事情除非你改变输入参数。
  • 知道了。谢谢。
【解决方案2】:

你的变量 y 没有改变,因为你改变了变量 p,它是你函数的本地变量。该变量在函数结束后与y无关。

【讨论】:

    【解决方案3】:

    两种选择:

    1. 要么让你的函数返回新列表:

      def proc2(p):
          return p + [1]
      
    2. 或者,让它修改p 就地(并可选择将其返回以进行更清晰的编码):

      def proc2(p):
          p += [1]  # this is not exactly the same as p = p + [1]
          return p  # <- optional!
      

    您的代码不是修改现有的p,而是创建一个新的,但不会与外部范围通信;结果当函数退出时死亡

    【讨论】:

      【解决方案4】:

      为了更好地理解这里发生了什么,检查 z 和 y 的 id,它们是不同的,这意味着 z 和 y 是不同的对象。更改其中一个不会影响另一个。

      y=[1,2] z=[1,2] print id(y), id(z)

      【讨论】:

        猜你喜欢
        • 2012-04-01
        • 2015-03-21
        • 1970-01-01
        • 2022-11-28
        • 1970-01-01
        • 2018-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多