Python中通过引用优雅地修改变量列表的方法是什么?

4

假设我有一个函数f(),它接受一个列表并返回该列表的变异。如果我想将该函数应用于我的类实例(i)中的五个成员变量,则可以这样做:

for x in [i.a, i.b, i.c, i.d, i.e]:
    x[:] = f(x)

1) 有没有更优雅的方式?我不想让f()修改传递的列表。

2) 如果我的变量保存的是简单的整数(无法使用切片表示法),是否也有一种方法?(在这种情况下,f() 还将采用 & 返回一个整数)


看起来 f 所期望的是一个列表,但你同时在遍历这个列表。 - Michael J. Barber
f函数所接受的列表存储在i.a、i.b等变量中。示例中的迭代是针对存储(引用,对于纯粹主义者)这些列表的变量进行的。好吧,实际上并不是针对变量本身进行的迭代,但这正是我想要的效果。 - David P Simons
3个回答

4

另一个解决方案,虽然可能不够优雅:

for x in ['a', 'b', 'c', 'd', 'e']:
    setattr(i, x, f(getattr(i, x)))

这在属性为列表的情况下不会像切片赋值那样产生相同的效果。但它仍然尽可能接近所需的效果,因此加1。 - aaronasterling
1
这正是我正在寻找的功能,尽管我希望它更易读。 - David P Simons

2

Python没有按引用传递的功能。最好的方法是编写一个函数来构建一个新列表,并将函数的结果赋值给原始列表。示例:

def double_list(x):
    return [item * 2 for item in x]

nums = [1, 2, 3, 4]
nums = double_list(nums) # now [2, 4, 6, 8]

或者更好的方法是:
nums = map(lambda x: x * 2, nums)

超级简单的例子,但你可以理解这个想法。如果你想从一个函数中改变一个列表,你将不得不返回修改后的列表并将其分配给原始列表。
你可能能够破解出一个解决方案,但最好还是按照正常的方式来做。
编辑
我意识到我实际上不知道你具体要做什么。也许如果你澄清你的具体任务,我们可以想出一个Python允许的解决方案?

这不会改变实际的列表对象,只会改变一个引用。 - aaronasterling
@aaronasterling 没错,你需要创建一个新列表(或将其分配给现有列表)。 - Rafe Kettler
2
@aaronasterling 那他就没那么幸运了。我也想要一架直升机 :D - Rafe Kettler

2

最终,您想要做的与Python的结构方式不兼容。如果您的变量是列表,则已经有了最优雅的方法来处理,但是对于数字则不可能。

这是因为在Python中不存在变量,只存在引用。所以i.x不是一个列表,而是一个指向列表的引用。同样,它也可以引用一个数字。因此,如果i.x引用了y,那么i.x = z实际上并不会改变值y,而是会改变i.x指向的内存位置。

大多数情况下,变量被视为包含值的盒子。名称在盒子上。在Python中,值是基本的,而“变量”只是标记,用于标识特定的值。一旦习惯了这种方式,就会感觉非常好。

在列表的情况下,您可以使用分片赋值,就像您已经在做的那样。这将允许所有引用列表的地方看到更改,因为您正在更改列表对象本身。对于数字的情况,则无法这样做,因为在Python中,数字是不可变的对象。这是有道理的。五就是五,你不能做太多改变它的事情。如果您知道或可以确定属性的名称,则可以使用setattr进行修改,但这不会更改可能已经存在的其他引用。

正如Rafe Kettler所说,如果您可以更具体地说明您实际想要做什么,那么我们可以想出一个简单而优雅的方法来实现它。


在我的情况下,我实际上更喜欢不影响列表的任何其他引用。因此,setattr方法会执行正确的操作(就像Antoine的建议一样),但并没有我正在寻找的优雅。 - David P Simons
@David 那么 setattr 就是唯一的方法了。因为你现在使用切片赋值的方式,其他引用将会引用修改后的列表。我同意,虽然它很丑陋。关于你尝试做什么的更多细节会得到更好的答案 ;) - aaronasterling
我的特定应用程序是这样的:我有一堆成员变量,每个变量都有一个文件路径列表,可能需要进行glob扩展和其他字符串操作。我的f()函数接受这样的列表并返回glob版本。我希望整个成员变量集合都通过这个过程。我想我可以将它们全部放在自己的字典中以便于迭代,但这是现有的代码。 - David P Simons
@David,将它们保存在字典中肯定是正确的方法。任何其他替代方法都需要你明确枚举你想要更改的属性。 - aaronasterling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接