我是否应该返回一个通过引用传递并修改的列表?

2024-04-20 10:29:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近发现python中的列表是通过引用自动传递的(除非使用了符号数组[:])。例如,这两个函数的作用相同:

def foo(z):
    z.append(3)

def bar(z):
    z.append(3)
    return z

x = [1, 2]
y = [1, 2]
foo(x)
bar(y)
print(x, y)

在此之前,我总是返回我操纵的数组,因为我认为我必须返回。现在,我明白这是多余的(也许效率很低),但返回值通常是提高代码可读性的好方法。我的问题是,做这两种方法中的任何一种都有什么问题/最佳实践是什么?有没有第三种选择我错过了?如果以前有人问过这个问题,我很抱歉,但我找不到任何真正能回答我问题的答案。你知道吗


Tags: 方法函数代码列表returnfoodef符号
3条回答

“最佳实践”从技术上讲是完全不修改:

def baz(z):
    return z + [3]

x = [1, 2]
y = baz(x)
print(x, y)

但总的来说,如果你限制自己返回一个新的对象或者修改一个对象,但不能同时返回和修改两个对象,那就更清楚了。你知道吗

标准库中有这样的例子,既修改了一个对象,又返回了一些东西(最重要的例子是list.pop()),但这是一个特例,因为它没有返回被修改的对象。你知道吗

通常,Python内置不会同时执行这两个操作,以避免混淆函数/方法是就地修改其参数还是返回新值。就地修改时,不执行return(使其隐式返回None)。例外情况是变异函数返回的不是变异对象(例如dict.popdict.setdefault)。你知道吗

一般来说,遵循相同的模式是个好主意,以避免混淆。你知道吗

这个答案是基于这样一个假设,即已经决定是修改您的输入,还是返回一个副本。你知道吗

正如您所指出的,是否返回修改过的对象是一个意见问题,因为结果在功能上是等价的。一般来说,而不是返回修改过的列表被认为是一种好的形式。根据Zen of Python(第2项):

Explicit is better than implicit.

标准图书馆证实了这一点。列表方法为此而臭名昭著:^{}, ^{}, ^{}^{},等等

Numpy也经常使用这种模式,因为它经常处理无法复制和返回的大型数据集。一个常见的例子是数组方法^{},不要与返回新副本的顶级函数^{}混淆。你知道吗

这个想法在很大程度上是Python思维方式的一部分。以下是Guido's email的摘录,解释了原因和原因:

I find the chaining form a threat to readability; it requires that the reader must be intimately familiar with each of the methods. The second [unchained] form makes it clear that each of these calls acts on the same object, and so even if you don't know the class and its methods very well, you can understand that the second and third call are applied to x (and that all calls are made for their side-effects), and not to something else.

相关问题 更多 >