是否有方法将variable number of arguments传递给函数并让它使用( *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个参数自定义它。我想创建一个接受任意数量的参数。因此,问题。
答案 0 :(得分:4)
否 - Python使用call by object-sharing,也称为按值调用。
澄清术语:您没有收到对象的深层副本,而是收到对象引用的副本。注意:这与call-by-reference不同!您可以将其视为按值调用,并且值是对象的引用。
因此,要回答您的问题,您会收到一个参数副本(对象引用)。您不能修改对象引用,就像它们是通过引用传递一样。如果你愿意,你可以制作一个新的修改过的副本,但从你的例子来看,这不是你想要的。调用范围不会看到您的更改。
如果您 mutate 您收到的对象,客户可以看到这些更改。
答案 1 :(得分:3)
原因
args[0] = 4
不起作用是因为,正如错误消息所说,args
一个元组,它是不可变的。因此,您首先需要将其转换为可变对象,例如:
>>> def foo( *args ):
print(args)
args = list(args)
args[0] = 42
print(args)
>>> foo(23)
(23,)
[42]
如果您提供更多信息,可以提供更多的pythonic解决方案,因为您所做的事情似乎很奇怪。此外,第二个代码似乎工作正常。
例如,以下工作正常并更改调用范围变量:
>>> 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'
答案 2 :(得分: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})