Python: 使用可变参数列表进行对象赋值
有没有一种方法可以让我们给一个函数传递可变数量的参数,并且用 ( *args, **keywords )
这种方式来改变这些参数呢?我试过几种方法,但要么没有任何变化,要么编译器报错:
def foo( *args ):
args[0] = 4
这让我遇到了 TypeError: object does not support assignment
(因为它们是元组)。或者
def foo( *args ):
plusOne = [ item+1 for item in args ]
args = plusOne
这根本没有任何效果。如果没有办法或者解决方案,我可以认输。
编辑:
为了更清楚地说明我为什么想这样做,考虑下面的情况:
class bar(object):
def __init__(self,obj):
self.obj = obj
def foo( input ):
input.obj = "something else"
如果我把我的 bar
对象传给 foo,我会看到状态发生变化。为了创建一个可以执行 deepcopy
的装饰器,重置所有这样的状态,我现在是为 N 个参数定制的。我想创建一个可以接受任意数量参数的装饰器。因此,我才有了这个问题。
3 个回答
1
如果你想要改变传给函数的参数,让它能够像这样工作:
>>> x, y = (10, 17)
>>> foo(x, y)
>>> print (x, y)
(11, 18)
那你就没那么幸运了,原因在于Mark的回答中已经说明了。
不过,如果你传递的是可变对象给你的函数,你可以改变这些对象,并在调用foo
之后看到结果:
def foo(*args):
for arg in args:
arg['value'] += 1
>>> d1 = {'value': 1}
>>> d2 = {'value': 2}
>>> foo(d1, d2)
>>> print (d1, d2)
({'value': 2}, {'value': 3})
3
之所以
args[0] = 4
不管用,是因为错误信息提到,args
是一个元组,而元组是不可变的。这意味着你不能直接修改它。所以,你需要先把它转换成可以修改的对象,比如这样:
>>> def foo( *args ):
print(args)
args = list(args)
args[0] = 42
print(args)
>>> foo(23)
(23,)
[42]
如果你提供更多信息,就可以给出更符合Python风格的解决方案,因为你现在的做法看起来有点奇怪。而且,第二段代码似乎运行得很好。
比如下面这个代码运行得很好,并且能改变调用范围内的变量:
>>> def spam(*a):
a[0][0] = 42
>>> l = [23, 32]
>>> spam(l)
>>> l
[42, 32]
原因是一样的:l
这个对象是可变的。你在你的例子中也可以看到这一点:
>>> def foo( *input ):
input[0].obj = "something else"
>>> b = bar('abc')
>>> foo(b)
>>> b.obj
'something else'