【问题标题】:Pass a List into Python Function将列表传递给 Python 函数
【发布时间】:2026-01-15 15:40:01
【问题描述】:

作为一个新的python程序员,我有两个关于list的问题,非常感谢你的建议:

问题一:

对于以下代码:

nums1 = [1,2,3,8,0,0,0]
m = 3
nums2 = [2,5,6]
n = 3
def merge(nums1, m, nums2, n):
    nums1[:] = sorted(nums1[:m]+nums2)
merge(nums1, m, nums2, n)
nums1

它的作用是:将list nums1和list nums2传递给merge函数,将它们与nums1中的前m项和nums2中的n项合并到list nums1中,并对list nums1进行排序。所以结果是: [1, 2, 2, 3, 5, 6] 所以我的问题是:既然 list nums1 是在函数合并范围之外定义的,它怎么有能力更新 nums1 呢?在下面的例子中:

x = 10
def reassign(x):
    x = 2
reassign(x)
x

变量 x 是在函数 reassign 之外定义的,而 reassign 函数无法更新在 reassign 之外定义的 x,这就是 x 返回 10 的原因。

问题 2:

在上面我提供的代码中,如果我这样写:

注意:我只是在分配 sorted(nums1[:m]+nums2) 时将 nums1[:] 修改为 nums1

nums1 = [1,2,3,8,0,0,0]
m = 3
nums2 = [2,5,6]
n = 3
def merge(nums1, m, nums2, n):
    nums1 = sorted(nums1[:m]+nums2)
merge(nums1, m, nums2, n)
nums1

nums1返回[1,2,3,8,0,0,0],所以我的问题是:在nums1后面加上[:]后,为什么函数有nums1的能力?该示例中的 [:] 是什么?

【问题讨论】:

  • 赋值和变异不是一回事。
  • 变量有范围,而不是对象。不同作用域的不同变量可以引用同一个对象,这就是传递参数时发生的情况
  • 所以,简单地说,使用nums[:] = whatever是一个mutator方法,并且sinve你的本地和全局变量都指的是同一个列表然后您会在局部变量中看到效果。阅读以下内容:nedbatchelder.com/text/names.html

标签: python list


【解决方案1】:

要复制您所说的内容,请执行以下操作:

var = 10
lst = [1, 2, 3]

def func():
    var = 11
    lst[:] = [1, 2, 3, 4]

func()
print(var, lst) 

上面会输出10 [1, 2, 3, 4]。现在注意以下几点:

var = 10
lst = [1, 2, 3]

def func():
    print(var)
    print(lst)

func()

输出10 [1, 2, 3] -- 所以我们知道函数可以访问全局变量,但在大多数情况下不能修改它们。现在让我们看看这两种情况(intlist): 两种情况如下:

  1. var 变量没有被修改,因为本地和全局范围的引用不同(虽然我们可以访问全局范围,但我们不能修改它)。我建议玩弄打印globals()locals() 以获得乐趣。如果我们这样做,这种情况可以解决:
def func():
    global var
    var = 11
  1. lst 变量正在使用[:] 表示法进行修改,因为引用here,切片分配[:] 使用operator 函数setitem()。因此,从技术上讲,lst[:] = 相当于这样做:
from operator import setitem

lst = [1, 2, 3]

# Both of these are equivalent. 
lst[:] = [1, 2, 3, 4] 
setitem(a, slice(0, len(a)), [1, 2, 3, 4])

setitem 不区分本地或全局范围。

【讨论】:

  • 这是slice assignment,没有复制。这是完全错误的:“因此,对于 lst 变量的情况,添加运算符 [:] 返回全局 lst 的副本,但引用附加到原始 lst。”注意,objects 既不是局部的也不是全局的,变量有作用域,而不是对象
  • 你是完全正确的@juanpa.arrivillaga - 对这个主题做了进一步的研究(让我自己最初混淆了)并在上面修复了,谢谢你指出这一点。
【解决方案2】:

(不要使用[:] 的东西。那太可怕了。)

我的非正式回答

当您说nums1[:] 时,Python 正在查找名为nums1 的全局列表。 然而,inside函数,Python首先关注new变量。为什么?
- 如果你在函数之外使用的任何变量名现在被限制在函数内用作不同的变量,那就太糟糕了

H = True # some variable.pretend it means "High"

def euro_height(inches):
    H = inches # since H is a nice abbrev for height in inches
    return H*2.54 # Centimeters

我不希望函数内的H 覆盖我已经存储的内容。因此,在euro_height 中,H 被视为不同的本地 变量,只有该函数才能看到和使用。如果我想从函数外部使用H,我必须首先告诉 Python 访问它。那我就可以用了。

H = True # some variable.pretend it means "High"

def euro_height(inches):
    global H
    print(H) # will say true

    renamed_var = inches # since H is a nice abbrev for height in inches
    return renamed_var*2.54 # Centimeters

如果我现在在函数内部分配H = inches,它将覆盖全局HTrue 值。因此,我重命名了它,因为已经有一个 H 我想使用。

这一切的名字叫做命名空间。希望您正在编写 Python 教程。当他们教授函数时,你会明白这一点。如果你不是,我建议你做一个教程。

有关此答案的更多信息,请查看此处的互动示例https://www.programiz.com/python-programming/global-local-nonlocal-variables

另外,永远不要再使用mylist[:]。 =) 语法很差。 它只返回整个列表。所以只需使用列表名称mylist。通过添加括号,您强制查找 og 全局变量,并创建了您的问题

【讨论】:

  • 你没有对列表进行切片,即 slice assignment 并且它的语法并不差,尽管许多人认为改变函数的参数是不好的做法。由于切片分配,它没有找到全局变量,它使用的是局部变量
  • 感谢您的澄清。至于切片分配,如果您仍然使用整个对象,它对我们[:] 毫无用处。如果你没有使用任何索引,那么你没有分配给任何特定的切片,只是整个列表 `nums1[:] = sorted(nums1[:m]+nums2)` 不需要[:] after nums1 在左边。这就是我所说的。
  • 是的,这完全是错误的。这不是没用,它是修改整个列表的惯用方式。如果您不使用切片分配,那么它不会修改列表。这是完全不同的两件事
【解决方案3】:

如果您感到困惑,请采取以下措施。

首先放置和改变不是一回事

nums1 = [1,2,3,8,0,0,0]
lst = None
m = 3
nums2 = [2,5,6]
n = 3
def merge(nums1, m, nums2, n):
    global lst 
    lst = sorted(nums1[:m]+nums2)
merge(nums1, m, nums2, n)
print(lst)

nums1[:] 表示您的整个列表。 如果您使用 nums1[:] 而不是 nums1 您可以使用 sorted(nums1[:m]+nums2) 更改以前的 nums1[:] 列表。当您执行此操作时,您的前一个列表和最新列表都会更改,因此您在 nums1 数组列表中更改新的附加变量会相互放置。但是,如果您只使用 nums1 而不是 nums1[:],那么最新的 nums1 现在指的是与前者不同的列表。

【讨论】: