4.4 KiB
在 Python 中==和的区别在于
原文:https://www.askpython.com/python/examples/difference-between-equal-to-and-is
操作符==和is在 Python 中执行非常相似的任务,但是它们彼此非常不同,并且处理一个非常有趣的概念:Python 如何在内存中存储变量。
理解==和 is 之间的区别
简单来说,
==检查两个操作数的值,如果相同,则返回True,否则返回False。is检查两个操作数的对象 ID,如果相同则返回True。
但是什么是对象 ID 呢?每个对象在内存中被分配一个 ID,两个变量可以指向同一个对象,这给了它们相同的对象 ID。
让我们用列表来看看它们的区别:
lst1 = [1,2,3]
lst2 = [1,2,3]
print(lst1 == lst2)
print(lst1 is lst2)
lst2 = lst1
print()
print(lst1 is lst2)
输出:
True
False
True
在上面的例子中,最初,内存中有两个列表,但是它们拥有完全相同的值。
==比较数值,因此运算返回True。- 但是
is检查它们是否指向同一个对象,这些列表实际上是不同的对象,所以返回False。 - 在这之后,我们使
lst2等于lst1,这使得lst2指向lst1所指向的地方,于是,is返回True。
所有这些对于整数来说是非常不同的,为了理解这一点,我们需要知道对象是如何存储在内存中的。
Python 中的内存分配
我们需要理解 Python 中对象的内存分配,以便在本教程中更进一步。
让我们举一个例子:
number = 10
在这里,我们知道number保存了值 10,但是它是如何存储在内存中的呢?在 Python 中,每个对象在内存中都有四个部分:
- Size–对于每个对象,保留 4 个字节来保存对象的大小。
- 引用计数–对于每个对象,保留 8 个字节,用于保存指向该对象的变量数量。所有这些对象都有这个对象的对象 ID。
- 对象类型–对于每个对象,保留 8 个字节,用于保存表示对象类型的信息。
- 对象值–另外 8 个字节为每个对象保留,它们保存对象的实际值。
现在,在上面的列表中,对象值和引用计数是这次讨论的重点。
因此,对于number = 10,内存中有一个对象,其对象值为 10,引用计数为 1,这意味着该对象的值为 10,有一个变量指向它,在我们的例子中是number。
现在让我们像这样声明另一个变量:
number_2 = number
print(number == number_2)
print(number is number_2)
现在,内存中会发生一件非常有趣的事情,不会有新的对象被创建,number_2也会指向number所指向的地方,对象的引用计数会增加到 2。
因此,number和number_2将具有相同的对象 ID,输出将是:
True
True
但是如果我们这样做呢?
num1 = 10
num2 = 10
print(num1 == num2)
print(num1 is num2)
在上面的示例中,输出将是:
True
True
从-5 到 256 的特殊数字
Python 认为从-5 到 256 的整数是常用的整数,因此这些整数的对象总是预定义的,您不能从内存中删除这些对象。
所以在 Python 代码的开始,所有这些对象的引用计数都是零,但是如果任何变量的值都在-5 到 256(包括-5 和 256)之间,那么就不会创建新的对象,所有的变量都会指向已经存在的对象。
所以在上面的代码中,10 的对象已经在内存中了,前两行只是创建了指向同一个对象的变量。
因此,对于下面的代码:
num1 = 257
num2 = 257
print(num1 == num2)
print(num1 is num2)
输出将是:
True
False
这是因为 python 会在每次声明整数时为超出该范围的整数创建新的实例。注意,如果我们已经做了num2 = num1,那么无论num1的值是多少,它们都将指向同一个对象。
结论
在本教程中,我们看到了==和is之间的区别,以及is如何有助于发现两个变量是否指向同一个内存位置。
我们还看到了从-5 到 256 的整数是如何缓存在内存中的,因为它们被认为是常用的(像'a'和'b'这样的字符也被类似地缓存),在这个范围内具有相同值的两个变量将指向同一个对象。