在Python中通过引用修改变量列表的优雅方法?

时间:2011-01-26 06:33:00

标签: python reference

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

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

1)有更优雅的方式吗?我不希望f()修改传递的列表。

2)如果我的变量包含一个简单的整数(不适用于切片表示法),还有一种方法吗? (f()也会在这种情况下采用&返回一个整数)

3 个答案:

答案 0 :(得分:4)

另一种解决方案,虽然它可能不优雅:

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

答案 1 :(得分: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允许的解决方案吗?

答案 2 :(得分:2)

最终,您想要做的是与Python的结构方式不兼容。在变量是列表的情况下,您已经拥有了最优雅的方法,但这对数字来说是不可能的。

这是因为Python中不存在变量参考。因此i.x不是列表,而是对列表的引用。同样,如果它引用了一个数字。因此,如果i.x引用y,则i.x = z实际上不会更改值y,它会更改i.x指向的内存中的位置。

大多数情况下,变量被视为包含值的框。名字在盒子上。在python中,值是基本的,“变量”只是挂在特定值上的标记。一旦你习惯它,这是非常好的。

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

正如Rafe Kettler所说,如果你能更具体地了解你真正想做的事情,那么我们可以提出一种简单优雅的方式来做到这一点。