您好我想了解Python如何通过引用传递。 我有一个例子:
>>>a = 1
>>>b = 1
>>>id(a);id(b)
140522779858088
140522779858088
这非常有意义,因为a和b都引用了与身份相同的值。我不太明白的是这个例子:
>>>a = 4.4
>>>b = 1.0+3.4
>>>id(a);id(b)
140522778796184
140522778796136
与此示例不同:
>>>a = 2
>>>b = 2 + 0
>>>id(a);id(b)
140522779858064
140522779858064
是因为在第3个例子中,0 int对象被视为" None"通过解释器并且不被认为需要与变量" a"引用(2)?而在第二个例子" b"添加两个不同的int对象,解释器为这两个要添加的对象分配内存,从而为变量提供变量" a" b"?
答案 0 :(得分:49)
在您的第一个示例中,由于实习,名称a
和b
都“引用”了同一个对象。赋值语句只产生一个具有相同id
的整数,因为它已经重用了一个恰好在内存中已经存在的预先存在的对象。这不是整数的可靠行为:
>>> a = 257
>>> b = 257
>>> id(a), id(b)
(30610608, 30610728)
如上所示,如果你选择一个足够大的整数,那么它的行为就像第二个例子中的浮点数一样。无论如何,实际的小整数是Python语言中的可选,这恰好是一个CPython实现细节:它是一种性能优化,旨在避免创建新对象的开销。我们可以通过缓存常用的整数实例来加快速度,但代价是Python解释器的内存占用量更高。
在处理Python时不要考虑“引用”和“值”,适用于C的模型在这里并不能很好地工作。而是想到“名字”和“对象”。
上图说明了您的第三个例子。 2
是一个对象,a
和b
是名称。我们可以使用不同的名称指向同一个对象。对象可以没有任何名称存在。
仅分配变量附加名称标签。 删除仅变量会删除名称标签。如果你记住这个想法,那么Python对象模型将永远不会让你感到惊讶。
答案 1 :(得分:8)
如上所述,here,CPython缓存从-5到256的整数。因此,具有相同值的此范围内的所有变量共享相同的id(尽管如此,我不打算对此进行赌注,但这是当前的实施)
浮游物没有这样的东西可能因为存在可能值的“无限”(因为浮点而不是无限大而是大),因此与整数相比,通过不同方法计算相同值的机会非常低。 / p>
>>> a=4.0
>>> b=4.0
>>> a is b
False
答案 2 :(得分:3)
Python变量始终是对象的引用。这些对象可以分为可变对象和不可变对象。
可以修改可变类型而不修改其id,因此指向此对象的每个变量都将更新。但是,不能以这种方式修改不可变对象,因此Python生成一个带有更改的新对象,并重新指定该变量以指向此新对象,因此更改之前变量的id将与之后的变量的id不匹配改变。
整数和浮点数是不可变的,因此在更改后它们将指向不同的对象,因此具有不同的ID。
问题是CPython"缓存"一些常见的整数值,以便没有多个对象具有相同的值以节省内存,2是这些缓存整数之一,因此每次变量指向整数2时它将具有相同的id(其对于不同的python执行,值将有所不同。)