This question already has an answer here:
这个问题在这里已有答案:
- “is” operator behaves unexpectedly with integers 11 answers
“是”运算符意外地使用整数11个答案
Hello I am trying to understand how Python's pass by reference works. I have an example:
您好我试图了解Python的引用如何通过工作。我有一个例子:
>>>a = 1
>>>b = 1
>>>id(a);id(b)
140522779858088
140522779858088
This makes perfect sense since a and b are both referencing the same value that they would have the identity. What I dont quite understand is how this example:
这是完全合理的,因为a和b都引用了与身份相同的值。我不太明白的是这个例子:
>>>a = 4.4
>>>b = 1.0+3.4
>>>id(a);id(b)
140522778796184
140522778796136
Is different from this example:
与此示例不同:
>>>a = 2
>>>b = 2 + 0
>>>id(a);id(b)
140522779858064
140522779858064
Is it because in the 3rd example the 0 int object is being viewed as "None" by the interpreter and is not being recognized as needing a different identity from the object which variable "a" is referencing(2)? Whereas in the 2nd example "b" is adding two different int objects and the interpreter is allocating memory for both of those objects to be added, which gives variable "a", a different identity from variable "b"?
是因为在第3个例子中,0 int对象被解释器视为“None”,并且没有被识别为需要与变量“a”引用的对象不同的身份(2)?而在第二个例子中,“b”是添加两个不同的int对象,而解释器是为要添加的两个对象分配内存,这给变量“a”,与变量“b”不同的标识?
3 个解决方案
#1
49
In your first example, the names a
and b
are both "referencing" the same object because of interning. The assignment statement resulted in an integer with the same id
only because it has reused a preexisting object that happened to be hanging around in memory already. That's not a reliable behavior of integers:
在您的第一个示例中,由于实习,名称a和b都“引用”同一对象。赋值语句导致一个具有相同id的整数,因为它已经重用了一个恰好在内存中已经存在的预先存在的对象。这不是整数的可靠行为:
>>> a = 257
>>> b = 257
>>> id(a), id(b)
(30610608, 30610728)
As demonstrated above, if you pick a big enough integer then it will behave as the floats in your second example behaved. And interning small integers is optional in the Python language anyway, this happens to be a CPython implementation detail: it's a performance optimization intended to avoid the overhead of creating a new object. We can speed things up by caching commonly used integer instances, at the cost of a higher memory footprint of the Python interpreter.
如上所示,如果您选择一个足够大的整数,那么它将表现为第二个示例中的浮点数。无论如何,实际的小整数在Python语言中是可选的,这恰好是CPython实现细节:它是一种性能优化,旨在避免创建新对象的开销。我们可以通过缓存常用的整数实例来加快速度,但代价是Python解释器的内存占用量更高。
Don't think about "reference" and "value" when dealing with Python, the model that works for C doesn't really work well here. Instead think of "names" and "objects".
在处理Python时不要考虑“引用”和“价值”,适用于C的模型在这里并不能很好地工作。而是想到“名字”和“对象”。
The diagram above illustrates your third example. 2
is an object, a
and b
are names. We can have different names pointing at the same object. And objects can exist without any name.
上图说明了您的第三个示例。 2是对象,a和b是名称。我们可以使用不同的名称指向同一个对象。对象可以没有任何名称存在。
Assigning a variable only attaches a nametag. And deleting a variable only removes a nametag. If you keep this idea in mind, then the Python object model will never surprise you again.
分配变量只会附加名称标签。删除变量只会删除名称标签。如果你记住这个想法,那么Python对象模型将永远不会让你感到惊讶。
#2
8
As stated here, CPython caches integers from -5 to 256. So all variables within this range with the same value share the same id (I wouldn't bet on that for future versions, though, but that's the current implementation)
如此处所述,CPython缓存从-5到256的整数。因此,具有相同值的此范围内的所有变量共享相同的id(但我不打算在未来的版本中使用它,但这是当前的实现)
There's no such thing for floats probably because there's an "infinity" of possible values (well not infinite but big because of floating point), so the chance of computing the same value by different means is really low compared to integers.
浮点数可能没有这样的东西可能是因为存在可能值的“无穷大”(因为浮点而不是无限但很大),因此与整数相比,通过不同方法计算相同值的机会非常低。
>>> a=4.0
>>> b=4.0
>>> a is b
False
#3
3
Python variables are always references to objects. These objects can be divided into mutable and immutable objects.
Python变量始终是对象的引用。这些对象可以分为可变对象和不可变对象。
A mutable type can be modified without its id being modified, thus every variable that points to this object will get updated. However, an immutable object can not be modified this way, so Python generates a new object with the changes and reassigns the variable to point to this new object, thus the id of the variable before the change will not match the id of the variable after the change.
可以修改可变类型而不修改其id,因此指向此对象的每个变量都将更新。但是,不能以这种方式修改不可变对象,因此Python生成一个带有更改的新对象,并重新指定该变量以指向此新对象,因此更改之前变量的id将与之后的变量的id不匹配改变。
Integers and floats are immutable, so after a change they will point to a different object and thus have different ids.
整数和浮点数是不可变的,因此在更改后它们将指向不同的对象,因此具有不同的ID。
The problem is that CPython "caches" some common integer values so that there are not multiple objects with the same value in order to save memory, and 2 is one of those cache-ed integers, so every time a variable points to the integer 2 it will have the same id (its value will be different for different python executions).
问题是CPython“缓存”了一些常见的整数值,因此没有多个对象具有相同的值以节省内存,2是这些缓存的整数之一,所以每次变量指向整数2它将具有相同的id(对于不同的python执行,它的值将不同)。
#1
49
In your first example, the names a
and b
are both "referencing" the same object because of interning. The assignment statement resulted in an integer with the same id
only because it has reused a preexisting object that happened to be hanging around in memory already. That's not a reliable behavior of integers:
在您的第一个示例中,由于实习,名称a和b都“引用”同一对象。赋值语句导致一个具有相同id的整数,因为它已经重用了一个恰好在内存中已经存在的预先存在的对象。这不是整数的可靠行为:
>>> a = 257
>>> b = 257
>>> id(a), id(b)
(30610608, 30610728)
As demonstrated above, if you pick a big enough integer then it will behave as the floats in your second example behaved. And interning small integers is optional in the Python language anyway, this happens to be a CPython implementation detail: it's a performance optimization intended to avoid the overhead of creating a new object. We can speed things up by caching commonly used integer instances, at the cost of a higher memory footprint of the Python interpreter.
如上所示,如果您选择一个足够大的整数,那么它将表现为第二个示例中的浮点数。无论如何,实际的小整数在Python语言中是可选的,这恰好是CPython实现细节:它是一种性能优化,旨在避免创建新对象的开销。我们可以通过缓存常用的整数实例来加快速度,但代价是Python解释器的内存占用量更高。
Don't think about "reference" and "value" when dealing with Python, the model that works for C doesn't really work well here. Instead think of "names" and "objects".
在处理Python时不要考虑“引用”和“价值”,适用于C的模型在这里并不能很好地工作。而是想到“名字”和“对象”。
The diagram above illustrates your third example. 2
is an object, a
and b
are names. We can have different names pointing at the same object. And objects can exist without any name.
上图说明了您的第三个示例。 2是对象,a和b是名称。我们可以使用不同的名称指向同一个对象。对象可以没有任何名称存在。
Assigning a variable only attaches a nametag. And deleting a variable only removes a nametag. If you keep this idea in mind, then the Python object model will never surprise you again.
分配变量只会附加名称标签。删除变量只会删除名称标签。如果你记住这个想法,那么Python对象模型将永远不会让你感到惊讶。
#2
8
As stated here, CPython caches integers from -5 to 256. So all variables within this range with the same value share the same id (I wouldn't bet on that for future versions, though, but that's the current implementation)
如此处所述,CPython缓存从-5到256的整数。因此,具有相同值的此范围内的所有变量共享相同的id(但我不打算在未来的版本中使用它,但这是当前的实现)
There's no such thing for floats probably because there's an "infinity" of possible values (well not infinite but big because of floating point), so the chance of computing the same value by different means is really low compared to integers.
浮点数可能没有这样的东西可能是因为存在可能值的“无穷大”(因为浮点而不是无限但很大),因此与整数相比,通过不同方法计算相同值的机会非常低。
>>> a=4.0
>>> b=4.0
>>> a is b
False
#3
3
Python variables are always references to objects. These objects can be divided into mutable and immutable objects.
Python变量始终是对象的引用。这些对象可以分为可变对象和不可变对象。
A mutable type can be modified without its id being modified, thus every variable that points to this object will get updated. However, an immutable object can not be modified this way, so Python generates a new object with the changes and reassigns the variable to point to this new object, thus the id of the variable before the change will not match the id of the variable after the change.
可以修改可变类型而不修改其id,因此指向此对象的每个变量都将更新。但是,不能以这种方式修改不可变对象,因此Python生成一个带有更改的新对象,并重新指定该变量以指向此新对象,因此更改之前变量的id将与之后的变量的id不匹配改变。
Integers and floats are immutable, so after a change they will point to a different object and thus have different ids.
整数和浮点数是不可变的,因此在更改后它们将指向不同的对象,因此具有不同的ID。
The problem is that CPython "caches" some common integer values so that there are not multiple objects with the same value in order to save memory, and 2 is one of those cache-ed integers, so every time a variable points to the integer 2 it will have the same id (its value will be different for different python executions).
问题是CPython“缓存”了一些常见的整数值,因此没有多个对象具有相同的值以节省内存,2是这些缓存的整数之一,所以每次变量指向整数2它将具有相同的id(对于不同的python执行,它的值将不同)。