【问题标题】:Python function not modifying the list passed to itPython函数不修改传递给它的列表
【发布时间】:2016-03-11 08:35:48
【问题描述】:
  1. 为什么函数x不修改传递给它的列表的内容?
  2. 如何更改 MWE,以便 x 修改传递给它的列表的内容?
>>> def x(mylist):
...     mylist = [ x for x in mylist if x > 5 ]
... 
>>> foo = [1,2,3,4,5,6,7,8,9,10]
>>> x(foo)
>>> print foo
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

【问题讨论】:

  • mylist = 使mylist 指向不同的列表。

标签: python list parameter-passing pass-by-reference pass-by-value


【解决方案1】:

该函数不会修改 x,因为它正在将名称 mylist 重新分配给一个新值。对此的替代方案将令人惊讶。

a = 1
b = a
b = 2
assert a == 1 # would you want a to be 2 here?

如果要替换内容,可以使用切片赋值来完成

def x(mylist):
    mylist[:] = [ x for x in mylist if x > 5 ]

python 中的赋值运算符不会进入任何方法调用。它是名称重新绑定的机制。但是,您可以实现__setitem__ 方法(就像list 所做的那样),它或多或少是运算符[]=

通过切片分配,您调用__setitem__ 并带有slice 参数,该参数表示“用...替换列表的这个切片”,其中... 是= 的右侧

【讨论】:

  • 我很困惑。在 Python 中,我认为a=1 创建了对 1 的引用,然后b=a 创建了对同一个 1 的另一个引用,因此执行b=2 实际上会更改a 引用的对象(1)。你能帮我看看我的错误吗?
  • @synaptik 你为什么会这样想?尤其是对于像整数这样的不可变对象,即使是一个微不足道的例子也会让你不屑一顾。
  • 您在前两步中是正确的,但b = 2 使b 引用了一个不同的 对象,其值为2,而不是修改内存中的1 .
  • 当您说b = a 时,您是在说“使b 指向a 指向的任何内容。”当您说b = 2 时,您是在说“使b 指向2”而不是“将b 已经指向的内容更改为2
【解决方案2】:

正如 Ryan Haining 解释的那样,x 正在重新分配列表。但是,它应该只修改列表项:

def x(mylist):
    for i in reversed(mylist):
        if not i > 5:
            mylist.remove(i)

请注意,您应该以相反的顺序遍历列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多