为什么某些类型的数据引用相同的内存位置

时间:2017-12-05 18:28:47

标签: python types tuples

问了这样一个问题。为什么只有类型只有str和具有相同变量的布尔引用一个内存位置:

a = 'something'
b = 'something'
if a is b: print('True') # True

但我们没有写任何地方a = b。因此,解释器看到字符串彼此相等,并引用了一个存储单元。

当然,如果我们为这两个变量中的任何一个赋予一个新值,就不存在冲突,所以现在该变量将引用另一个内存位置

b = 'something more'
if a is b: print('True') # False

类型为boolean,所有相同的

a = True
b = True
if a is b: print('True') # True

我首先想到所有可变类型都会发生这种情况。但不是。还有一个不变的类型 - 元组。但它有不同的行为,也就是说,当我们为变量分配相同的值时,我们已经引用了不同的存储单元。为什么这只发生在不可变类型的元组

a = (1,9,8)
b = (1,9,8)
if a is b: print('True') # False

2 个答案:

答案 0 :(得分:0)

在Python中,==检查值是否相等,而is检查基本上是否是同一个对象,如下所示:
id(object) == id(object)
Python有一些内置的单例,它开始于(我猜的是较低的整数和一些常用的字符串) 所以,如果你深入研究你的陈述

a = 'something'
b = 'something'
id(a)
# 139702804094704
id(b)
# 139702804094704
a is b
# True

但如果你稍微改变一下:

a = 'something else'
b = 'something else'
id(a)
# 139702804150640
id(b)
# 139702804159152
a is b
# False

我们得到了False,因为Python这次使用ab的内存位置不同,这与之前不同。
我的猜测是使用元组(如果我弄错了,有人会纠正我)每次创建时都会分配不同的内存。

答案 1 :(得分:0)

为什么某些类型会缓存值?因为你不应该注意到差异!

is是一个非常专业的运营商。几乎总是你应该使用==代替,这将完全符合您的要求。

您希望使用is而不是==的情况基本上就是当您处理重载==行为的对象时,并不意味着您想要它意思是,或者你担心你可能会处理这些对象。

如果您不确定是否处理此类对象,则可能不是,这意味着==始终是正确的,您不必使用{{1} }。

is与已知的单一对象(如is)一起使用可能是“样式点”的问题,但在那里使用None并没有错(再次,在没有==)的病态实施。

如果你正在处理可能不值得信任的对象,那么你应该从不做任何可以调用他们控制的方法的东西....这是一个使用==的好地方。但几乎没有人这样做,那些做的人应该知道恶意对象可能导致问题的其他其他方式。

如果某个对象错误地实现了is ,那么您可能会遇到各种奇怪的问题。在调试这些问题的过程中,您当然可以并且应该使用==!但这不应该是您在编写代码中比较对象的常用方法。

如果您正在处理的对象以特别昂贵的方式实现is,那么您可能希望使用is而不是==的另一种情况是性能优化。根本不会经常出现这种情况,并且大多数情况下有更好的方法来减少比较两个对象的次数(例如通过比较哈希代码),这最终会产生更好的效果在没有对正确性提出质疑的情况下进行表现。

如果你在语义上想要相等比较的任何地方使用==,那么你甚至不会注意到某些类型偷偷地重用你的实例。