关于python:Python-中对象的比较操作-与-is

5次阅读

共计 1997 个字符,预计需要花费 5 分钟才能阅读完成。

Python 中对象的比拟有两种形式 ==is。两种形式都能判断操作符两侧的变量值是否相等,那么它们的区别是什么呢?通过上面的介绍咱们来一探到底。

比拟操作符通常用于条件语句,如下示例:

if a == b:
    pass
if a is False:
    pass

==is 的区别

== 操作符比拟对象的值是否相等。小明有一块 劳力士 手表,小李也有一块同款 劳力士 手表,这时咱们就认为这两块手表相等。

小明的手表 = 劳力士
小李的手表 = 劳力士
小明的手表 == 小李的手表

is 操作符比拟对象的身份标识是否相等,即对象在内存中的地址是否雷同,如果两个对象的身份标识相等,就阐明它们是同一个对象。小明的爸爸称说小明叫 儿子 ,小明的女朋友称说小明叫 老公 ,但这两个称说都代表 小明 这个人,即为同一个对象。

爸爸的儿子 = 小明
女朋友的老公 = 小明
爸爸的儿子 is 女朋友的老公

接下来就用代码来展现一下 ==is 的区别:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a == b
True
>>> a is b
False
>>> id(a)
24603664
>>> id(b)
24603144
>>> a = [1, 2, 3]
>>> b = a
>>> a == b
True
>>> a is b
True
>>> id(a)
24604144
>>> id(b)
24604144

在 Python 中 id 函数接管一个对象作为参数,并返回该对象在内存中的地址。
由以上代码能够剖析出:== 操作符只比拟两个对象的值是否相等,但不比拟两个对象是否为同一个对象;而 is 操作符并不是比拟两个对象的值是否相等,而是会确认两个对象是否为同一个对象,如果为同一个对象,那么它们的值天然相等。

Python 小整数对象池

以上两段代码曾经可能体现出 ==is 的区别,不过 Python 中也有一些非凡状况,来看上面例子:

>>> a = 5
>>> b = 5
>>> a == b
True
>>> a is b
True
>>> id(a)
1730274128
>>> id(b)
1730274128
>>> a = 257
>>> b = 257
>>> a == b
True
>>> a is b
False
>>> id(a)
48558688
>>> id(b)
48558720

以上代码看起来就很怪异了,同样的比拟操作,只是换了一个数字后果就不同了。
其实呈现以上后果的起因在于 Python 本身。Python 出于性能上的思考,在解释器启动的时候就曾经将 -5256 的整数创立到内存中了。而当咱们须要创立值在 -5256int 数字的时候,Python 并不会新开拓一块内存去创立数字,而是间接将已存在的对象返回。
然而如果新创建的数字不在这个范畴,Python 就会为每个变量独自开拓本人的内存空间。

Python intern 机制

再来看上面对于字符串比拟的例子:

>>> a = 'hello world'
>>> b = 'hello world'
>>> a == b
True
>>> a is b
False
>>> id(a)
49465408
>>> id(b)
49465448
>>> a = 'hello'
>>> b = 'hello'
>>> a == b
True
>>> a is b
True
>>> id(a)
49429152
>>> id(b)
49429152

想必依据之前数字比拟的例子,你大略也能猜测到以上代码后果不同的起因了。事实上,以上后果同样是 Python 出于对性能的思考,不过这次 Python 并没有事后将 hello 字符串创立到内存中,而是应用了一种叫 intern 的机制。
对于 intern 机制在这里咱们不去深究,当前有机会专门写一篇博客来介绍。总之你须要晓得在某些场景下,Python 会对字符串开启 intern 机制来进步性能,从而导致呈现下面示例代码的后果。

==is 各自的实用场景

什么时候用 ==、什么时候用 is 呢?
当咱们须要比拟一个变量与一个 单例 的时候,应该应用 is,其余状况通常应用 ==
例如拿一个变量去跟 TrueFalse 进行比拟的时候就应该应用 is,因为用 is 的比拟的速度要比用 == 更快。
is 比拟对象的时候,只须要判断它们是否处于同一块内存地址即可,而用 == 比拟更慢的起因在于当用 == 去比拟对象的时候会调用对象的 __eq__() 办法,而 __eq__() 办法通常会被重载,执行其外部逻辑往往会多花一些工夫。

以下就是一个重载对象 __eq__() 办法的例子:

class MyList(object):
    def __init__(self, *args):
        self._list = [*args]

    def __eq__(self, other):
        result = False
        for i in self._list:
            for j in other._list:
                if i == j:
                    break
            else:
                break
        else:
            result = True
        return result

li_1 = MyList(1, 2, 3)
li_2 = MyList(1, 2, 3)
print(li_1 == li_2)  # True

你能够自行尝试批改 __eq__() 办法外部的逻辑来察看其后果。

正文完
 0