我编写了以下代码来检查整数是否按值或引用传递。
foo = 1
def f(bar):
print id(foo) == id(bar)
bar += 1
print foo, bar
f(foo)
我得到的输出是
True
1, 2
从Python文档来看,id(object)
返回对象的标识。在里面CPython http://en.wikipedia.org/wiki/CPython实现时,这是对象在内存中的地址。由于函数体中的第一条语句返回True
, 它的意思是foo
已通过引用传递,但为什么最后一条语句打印1, 2
代替2, 2
?
在 Python 中,就像在许多现代 OO 语言中一样
foo = 1
实际上创建了一个具有该值的对象1
并分配对别名的引用foo
。 foo 的内部类型是PyInt对象 http://docs.python.org/2/c-api/int.html。这意味着 Python 不使用 CPU/硬件 int 类型,它始终使用对象在内部处理数字。正确的说法是“普通整数 http://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex", btw.
但创建对象是非常昂贵的。这就是 Python 为一些数字保留内部缓存的原因。意思是:
foo = 1
bar = 1
assert id(foo) == id(bar)
这是无法保证的,它只是实现的副作用。
Python 中的数字类型也是不可变的。所以尽管bar
在你的例子中是缓存的 int 数字的别名,改变bar
不修改内部值。反而,bar
指向另一个实例,这就是 id 更改的原因。
由于上述优化,这也有效:
foo = 1
bar = 1
assert id(foo) == id(bar)
bar += 1
assert id(foo) != id(bar)
bar -= 1
assert id(foo) == id(bar)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)