这可能更适合讨论组,但我并不精通 语言的内在(甚至是语言本身)。无论如何,困扰我的是:
如果python允许使用nonlocal
关键字对外部作用域进行干扰(副作用),那么为什么它不允许对函数参数进行类似的干扰
允许通过引用传递参数:
现在可能:
>>> def outer():
x = 1
def inner():
nonlocal x
x = 2
print("inner:", x)
inner()
print("outer:", x)
>>> outer()
inner: 2
outer: 2
为什么不 - 或者如果我们有什么可能出错:
>>> def outer():
x = 1
def inner(byref x):
x = 2
print("inner:", x)
inner(x)
print("outer:", x)
>>> outer()
inner: 2
outer: 2
(使用某些关键字,例如'byref'或'nonlocal,仅用于说明)。
答案 0 :(得分:2)
Python总是使用参考值传递参数。请参阅此处的this链接,特别是用户提供的详细回复 pepr
同样this链接有关于如何在python中传递参数的确切详细讨论,并且还可以模拟 pass-by-reference - 请参阅对此接受的答案的编辑问题
如果您希望深入研究 - 请参阅此Effbot文章,该文章还包含围绕同一主题的一些辩论/讨论。
答案 1 :(得分:1)
这是不可能的,因为Python根本没有“变量”的概念。 Python程序中的所有名称都是对象的引用。因此,在调用函数或方法时,只能传递对象的引用。这称为通过参考值传递。
但是,无法获得对现有参考的引用。在这方面,引用是Python世界中唯一的“非一流”公民。
程序中的名称引用了两种对象:immutable(例如string,int,tuple)是一个可变的(例如list,set,大多数用户类)。
您可以在可变对象上调用实际上修改对象状态的方法,这看起来类似于使用C ++等语言传递对象的引用。除此之外,通过引用传递在Python中没有多大意义。
请参阅Prahalad Deshpande对某些链接的回答。
答案 2 :(得分:1)
假设您允许引用参数。那么,当您执行以下操作时会发生什么?
def f(byref x):
print x
print x
x = 3
class Foo(object):
def __init__(self):
self.count = 0
@property
def x(self):
count += 1
return count
f(Foo().x)
什么时候叫getter?它叫多少次?这会打印1
两次,还是打印1
,然后是2
,或2
,然后是3
?由于没有setter,当你尝试分配给x
时会发生什么?
在另一种语言中,变量是放置东西而不是值的名称的地方,这不是问题。 Foo().x
一旦评估就会有一个内存位置,而f
会将该内存位置用于其x
参数。在Python中,它不像那样工作。您无法传递1
的内存位置并更改其内容,因为其他代码会突然发现1
神奇地2
。 Python的名称语义和属性/项getter / setter使得引用参数比C ++这样的语言更令人困惑,因为它们已经让人感到困惑和容易出错。
答案 3 :(得分:0)
在Python int
中,对象是不可变的。当您认为自己正在更改x
的值时,您实际上是在不同的内存位置创建新的int
并让x
引用它。