Python中的整数是通过值还是引用传递的?

aja*_*jay 2 python

我编写了以下代码来检查整数是通过值还是引用传递的.

foo = 1

def f(bar):
    print id(foo) == id(bar)
    bar += 1
    print foo, bar

f(foo)
Run Code Online (Sandbox Code Playgroud)

我得到的输出是

True
1, 2
Run Code Online (Sandbox Code Playgroud)

从Python文档中,id(object)返回对象的标识.在CPython实现中,这是内存中对象的地址.由于函数体中的第一个语句返回True,它表示foo已通过引用传递,但为什么最后一个语句打印1, 2而不是2, 2

Aar*_*lla 5

在Python中,就像许多现代OO语言一样

foo = 1
Run Code Online (Sandbox Code Playgroud)

实际上创建一个具有该值的对象,1并为该别名分配一个引用foo.foo的内部类型是PyIntObject.这意味着Python不使用CPU /硬件int类型,它总是使用对象在内部处理数字.正确的术语是" 普通整数 ",顺便说一下.

但是创建对象非常昂贵.这就是为什么Python为少数数字保留内部缓存的原因.意思是:

foo = 1
bar = 1
assert id(foo) == id(bar)
Run Code Online (Sandbox Code Playgroud)

这不能保证,这只是实施的副作用.

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)
Run Code Online (Sandbox Code Playgroud)