Python中is、in、==之间的区别

Python 中,对象相等性比较相关关键字包括is、in,比较运算符有 ==

  • is判断两个对象的标识符是否相等
  • in用于成员检测
  • ==用于判断值或内容是否相等,默认是基于两个对象的标识号比较

也就是说,如果 a is b 为 True 且如果按照默认行为,意味着 a==b 也为 True

Python 中,对象相等性比较相关关键字包括is、in,比较运算符有 ==

  • is判断两个对象的标识符是否相等
  • in用于成员检测
  • ==用于判断值或内容是否相等,默认是基于两个对象的标识号比较

也就是说,如果 a is b 为 True 且如果按照默认行为,意味着 a==b 也为 True

is 判断标识号是否相等

is是Python身份运算符,用于判断两个对象的标识符是否相等(python中万物皆对象),实质是用于比较两个对象是否指向同一存储单元,以下有几点is的使用方法:

(1) Python 中使用 id() 函数获取对象的标识号,可以理解为内存地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
In [49]: a = 1
In [50]: b = 1
In [51]: id(a)
Out[51]: 140708412432784
In [52]: id(b)
Out[52]: 140708412432784
In [53]: a is b
Out[53]: True

In [54]: s1 = 'abc'
In [55]: s2 = 'abc'
In [56]: id(s1)
Out[56]: 1554773534064
In [57]: id(s2)
Out[57]: 1554773534064
In [58]: s1 is s2
Out[58]: True

(2) 由于创建的两个列表实例位于不同的内存地址,所以它们的标识号不等,即便对于两个空列表实例也一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In [77]: a = [1,2]
In [78]: b = [1,2]
In [79]: id(a)
Out[79]: 1552668915144
In [80]: id(b)
Out[80]: 1552668915208
In [81]: a is b
Out[81]: False
In [83]: a is not b
Out[83]: True
In [84]: not a is b
Out[84]: True

In [85]: a = []
In [86]: b = []
In [87]: id(a)
Out[87]: 1552668699208
In [88]: id(b)
Out[88]: 1552669048456
In [89]: a is b
Out[89]: False

(3) 对于序列型、字典型、集合型对象,一个对象实例指向另一个对象实例,is 比较才返回真值。

1
2
3
4
In [95]: a = [1,2]
In [96]: b = a
In [97]: a is b
Out[97]: True

(4) 需要注意的是,Python 解释器,对位于区间 [-5,256] 内的小整数,会进行缓存,不在该范围内的不会缓存,因此会出现如下现象:

1
2
3
4
5
6
7
8
In [90]: a = 12345
In [91]: b = 12345
In [92]: id(a)
Out[92]: 1552668913040
In [93]: id(b)
Out[93]: 1552668911312
In [94]: a is b
Out[94]: False

(5) Python 中 None 对象是一个单例类的实例,具有唯一的标识号,在判断某个对象是否为 None 时,最便捷的做法:variable is None,如下:

1
2
3
4
5
6
7
In [98]: id(None)
Out[98]: 140708411956448
In [99]: a = None
In [100]: a is None
Out[100]: True
In [101]: id(a)
Out[101]: 140708411956448

in 用于成员检测

  • 如果元素 i 是 s 的成员,则 i in s 为 True;
  • 若不是 s 的成员,则返回 False,也就是i not in s 为 True

in 是判断成员是否属于某个序列,in 后即可以跟字符串,也可以跟列表,实际上各种集合类型都可以。

(1) 对于字符串类型,i in s 为 True,意味着 i 是 s 的子串。

1
2
3
4
5
In [104]: '234' in '12345'
Out[104]: True
# 当然。也可以用字符串的find()方法判断
In [105]: '12345'.find('234')
Out[105]: 1

(2)列表中任何数据类型的元素都可以用in判断,同理,元祖和集合也可以这样做

1
2
3
4
5
6
7
In [106]: [1,2] in [[1,2],3,'abc']
Out[106]: True
In [107]: lst = [[1,2],3,'abc']
In [109]: [1,2] in lst
Out[109]: True
In [110]: 'abc' in lst
Out[110]: True

(3)对于字典类型,in 操作判断 i 是否是字典的键,但不能直接判断值,如果要判断一个值是否在字典中,可以用字典的values()方法

1
2
3
4
5
6
7
8
9
10
11
12
In [111]: dct = {'a':12,'b':35,'key':'abc'}
In [112]: 'a' in dct
Out[112]: True
In [113]: 'key' in dct
Out[113]: True

In [114]: 12 in dct
Out[114]: False
In [115]: 12 in dct.values()
Out[115]: True
In [116]: 'abc' in dct.values()
Out[116]: True

(4)对于自定义类型,判断是否位于序列类型中,需要重写序列类型的 魔法方法 contains

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Node():
def __init__(self,value):
self.value = value

class Nodes(list):
def __contains__(self,node):
for s in self:
if s.value == node.value:
return True
return False

n1 = Node('linear')
n2 = Node('sigmoid')
a = Nodes()
a.extend([n1,n2])
n3 = Node('linear')
print(n3 in a) # True
n4 = Node('tanh')
print(n4 in a) # False

== 判断值是否相等

(1) 对于数值型、字符串、列表、字典、集合,默认只要元素值相等,== 比较结果是 True

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
In [117]: str1 = 'abc'
In [118]: str2 = 'abc'
In [119]: str1 == str2
Out[119]: True

In [120]: a = [1,2]
In [123]: b = [1,2]
In [124]: a == b
Out[124]: True

In [125]: a = [[1,2],3]
In [126]: b = [[1,2],3]
In [127]: a == b
Out[127]: True

In [128]: a = {'a':1,'b':2}
In [129]: b = {'a':1,'b':2}
In [130]: a == b
Out[130]: True

In [131]: a = {1,2}
In [132]: b = {1,2}
In [133]: a == b
Out[133]: True

(2)对于自定义类型,当所有属性取值完全相同的两个实例,判断 == 时,返回 False。如果需要用==判断两个对象是否相等,需要重写方法 __eq__,使用__dict__获取实例的所有属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Node():
def __init__(self,value):
self.value = value
def __eq__(self,node):
return self.__dict__ == node.__dict__

n1 = Node('linear')
n2 = Node('sigmoid')
n3 = Node('linear')

print(n1.__dict__) # {'value': 'linear'}
print(n1 == n2) # False
print(n1 == n3) # True