为什么以下在Python中出现意外行为?
>>> a = 256
>>> b = 256
>>> a is b
True # This is an expected result
>>> a = 257
>>> b = 257
>>> a is b
False # What happened here? Why is this False?
>>> 257 is 257
True # Yet the literal numbers compare properly
Run Code Online (Sandbox Code Playgroud)
我使用的是Python 2.5.2.尝试一些不同版本的Python,似乎Python 2.3.3显示了99到100之间的上述行为.
基于以上所述,我可以假设Python在内部实现,使得"小"整数以不同于大整数的方式存储,is运算符可以区分.为什么泄漏抽象?当我不知道它们是否是数字时,比较两个任意对象以查看它们是否相同的更好的方法是什么?
我阅读了Python 2文档并注意到了这个id()函数:
返回对象的"标识".这是一个整数(或长整数),保证在该生命周期内该对象是唯一且恒定的.具有非重叠生存期的两个对象可以具有相同的id()值.
CPython实现细节:这是内存中对象的地址.
所以,我通过使用id()列表进行了实验:
>>> list = [1,2,3]
>>> id(list[0])
31186196
>>> id(list[1])
31907092 // increased by 896
>>> id(list[2])
31907080 // decreased by 12
Run Code Online (Sandbox Code Playgroud)
函数返回的整数是多少?它是C中内存地址的同义词吗?如果是这样,为什么整数不对应于数据类型的大小?
何时id()在实践中使用?
我正在尝试使用 id 来理解 python 中的默认值
def f(x=5000):
print(id(x))
x=40000
print(id(x))
print()
f()
f()
Run Code Online (Sandbox Code Playgroud)
这给出了输出
2187265500336
2187265501488
2187265500336
2187265501488
Run Code Online (Sandbox Code Playgroud)
我明白为什么第一个打印语句是相同的。这是因为默认值 x 是在定义函数时计算的。
然而,在这两种情况下,第二个 print 语句给出相同的 id 让我感到困惑,我在其他地方找不到在线答案。考虑
a=100000
print(id(a))
a=400000
print(id(a))
a=100000
print(id(a))
a=400000
print(id(a))
Run Code Online (Sandbox Code Playgroud)
这给出了输出
2187265558768
2187265558608
2187265559440
2187265558032
Run Code Online (Sandbox Code Playgroud)
是什么造成了这两种情况的差异?在函数内部,当我们在不同的函数调用中重新分配变量时,它会获得相同的 id,但是当我们将变量重新分配为与之前在函数外部相同的值时,不会发生这种情况
编辑回应 @Barmar 的评论和与理解 python id() uniqueness相关的问题。我有点理解,但不完全理解。我现在最好的猜测是(1)内存被保留以供将来使用,如下面示例中的注释(2)中所述,似乎有一些根本原因为什么每次都会将相同的内存分配给 x,即使其他内存也是如此内存已分配。这是因为缓存优化吗?
缓存优化意味着,在人们可能天真地认为应该获得新对象的情况下,并不总是能保证获得新对象,但这并不以任何方式违反 ID 的唯一性保证。像 int 和 str 这样的内置类型可能有一些缓存优化,但它们遵循完全相同的规则:如果它们同时存在,并且它们的 ID 相同,那么它们是同一个对象。
def f(x=5000):
print(id(x))
c=23000
d=12444
x=40000
w=23444
print(id(x))
print()
f()
f()
Run Code Online (Sandbox Code Playgroud)
2187265559440
2187265559376
2187265559440
2187265559376
Run Code Online (Sandbox Code Playgroud)
这里我们分配了几个新变量,但每次重新分配时都会将相同的 id 分配给变量 x。
关于@dont just …