[英]why can't I change the variables using kwargs inside a function? [duplicate]
这个问题已经在这里有了答案:
Python初学者的问题。 我正在尝试更改函数中某些变量的值,但我不明白为什么有时它起作用而有时却不起作用。 所以我想知道幕后发生的事情。 如果我写:
def assign(self, **kwargs):
kwargs['test'] = 3
kwargs['steps'] += [1]
t = 1
s = []
assign(test=t, steps=s)
print(t)
print(s)
这仍然打印
1
[]
现在,如果我将功能分配给
def assign(self, **kwargs):
kwargs['test'] += 3
kwargs['steps'] += [1, 2, 3]
它会更改列表,但不会更改整数。 因此,我想这与整数是不可变且列表是可变的这一事实有关。 因此,我当时考虑使用字典来确保更改我的变量。 因此:
dict = {'test':1, 'steps': []}
assign(**dict)
print(dict)
仍然打印
{'test': 1, 'steps': [1, 2, 3]}
具有完全相同的行为,所以现在我真的很困惑。 似乎在解unpacked
字典时,我不再将引用传递给字典变量了,以便这些unpacked
变量按值复制吗? 实现我当时想做的最好的方法是什么?
UPDATE
由于与@ 6502的讨论,
在Python中,由于无法使用“指针”或“引用”,因此无法更改已传递给函数的参数。
最pythonic的方式是不这样做。 一个函数接收参数并提供结果。 如果参数是可变的,则可以更改其状态,但是认为不需要更改调用参数本身。
然后我决定返回一本包含结果的字典:
def assign(self, **kwargs):
kwargs['test'] += 3
kwargs['steps'] += [1, 2, 3]
return kwargs
dict = {'test':1, 'steps': []}
dict = assign(**dict)
print(dict)
这当然可行,但是我想知道对大数据的影响,因为在我看来(来自C ++世界)周围有很多复制。
第一个示例是错误的,您得到s=[1]
:
这是因为列表s
是一个参数, steps
然后您更改了该列表的内容。 简单得多:
def assign(step):
step += [1] # change the contents of the list
s = []
assign(step=s)
print(s) # gives [1]
这与关键字参数或dict扩展无关。 如果使用**或直接将关键字作为参数输入,则绝对相同。
不要试图通过引用传递变量。 使用python不可能。 请改用返回值。
def assign(test, steps):
return 3, steps + [1]
t, s = assign(3, [])
一种合理化语义的简单方法是考虑所有Python值的确是指向对象的指针,并且这些指针始终按值传递。
如果更改了指向调用方的对象,则可以看到该突变,但是,如果您分配了变量,则只是在更改它指向的对象,而调用方将不会注意到。
在Python中,由于无法使用“指针”或“引用”,因此无法更改已传递给函数的参数。 更改变量的唯一方法是使用其名称。
一种解决方法(在Python 3中)是传递一个可以访问本地的闭包,例如:
def foo(x, y, set_result):
set_result(x + y)
def bar():
res = None
def set_res(x):
nonlocal res
res = x
foo(10, 20, set_res)
print(res)
但是,这种技巧是很少需要的,因为在带有引用参数传递的语言中,最常见的用途是返回多个值,例如(C ++)
bool read_xy(double& x, double& y);
函数需要返回三个值x,y和成功标志。
在Python中,但这不是必需的,因为您可以编写
return x, y
并用作
x, y = read_xy()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.