Python 中的比较运算符(也叫 Python 关系运算符)会查看两个操作数的_值_,并在 comparison 条件成立或不成立时返回布尔值 True 或 False。
下表列出了最常见的 Python 比较运算符:
| 运算符 | 运算 | 描述 |
|---|---|---|
> |
“大于” | 如果 a 的值严格大于 b,则 a > b 为 True
|
< |
“小于” | 如果 a 的值严格小于 b,则 a < b 为 True
|
== |
“等于” | 如果 a 的值严格等于 b,则 a == b 为 True
|
>= |
“大于或等于” | 如果 a > b,或者按值 a == b,则 a >= b 为 True
|
<= |
“小于或等于” | 如果 a < b,或者按值 a == b,则 a <= b 为 True
|
!= |
“不等于” | 如果 a == b 为 False,则 a != b 为 True
|
is |
“身份” | 当 且仅当 a 和 b 是同一个_对象_时,a is b 为 True
|
is not |
“取反的身份” | 当 且仅当 a 和 b 不是同一个_对象_时,a is not b 为 True
|
in |
“包含测试” | 如果 a 是 b 的成员、子集或元素,则 a in b 为 True
|
not in |
“取反的包含测试” | 如果 a 不是 b 的成员、子集或元素,则 a not in b 为 True
|
它们的优先级都相同(高于布尔运算,但低于算术运算或位运算)。
类型不同的对象(数值类型除外)默认永远不会比较为相等。
除非 class 定义了特殊的富比较方法,用来定制 object 的默认比较行为,否则同一个 class 的不同实例也_不会_比较为相等。
想了解(多得多)的细节,请参阅 Python 文档中的值比较。
数值类型(大多)是这个类型匹配规则的例外。
只要类型能够为比较而隐式转换,integer 可以被认为等于 float(或者 octal 等于 hexadecimal)。
对于其他数值类型(复数、小数、分数),比较运算符被定义在它们“说得通”的地方(也就是隐式转换不会改变结果的地方),但如果底层对象无法为比较而准确转换,就会抛出 TypeError。
关于 Python 数值转换所用规则的更多信息,请参阅 Python 文档中的算术转换。
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex
# number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
数字与 NaN(非数字)类型之间的任何有序比较都是 False。
Python 对 NaN 的定义有一个令人困惑的副作用:NaN 永远不会比较为等于 NaN。
如果你好奇 Python 为什么这样定义 NaN,这篇围绕国际标准制定的 Stack Overflow 帖子 值得一读。
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
字符串(str)按字典序比较,依据的是它们各自的 Unicode 码点(也就是把 str 中每个码点传给内置函数 ord() 所得到的结果,该函数返回一个 int)。
如果两个字符串的所有码点都相同,并且_顺序也相同_,这两个字符串就被视为相等。
这种比较是“成对”进行的:第一个对第一个,第二个对第二个,依此类推。
在 Python 3.x 中,str 和 bytes 不能直接强制转换或比较。
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
容器数据类型(lists、tuples、sets、dicts 等)也按字典序比较:如果两个容器有相同的数据并且有相同的数据类型,它们就相等(对于 lists 和 tuples,它们还必须具有相同的顺序),否则不相等。
>>> [1, 2] == [1, 2]
True
# But if the data is not in the same order, they are not equal.
>>> [2, 1] == [1, 2]
False
# The same holds true for tuples
>>> (3,4,5) == (5,4,3)
False
# Length is also compared
>>> [1, 2] < [1, 2, 3]
True
# Comparing dicts
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 18}
False
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 19}
True
比较运算符可以_任意_链式连接。
注意,表达式的求值是从 left 到 right 进行的。
例如,x < y <= z 等价于 x < y and y <= z,区别在于 y 只求值一次。
在这两种情况下,当发现 x < y 为 False 时,z 根本不会被_求值_。
这通常被称为 short-circuit evaluation:如果表达式的真值已经确定,求值就会停止。
许多布尔运算符、函数以及 Python 中的链式比较都支持 Short circuiting。
与 C、C++、C# 和 Java 等许多其他编程语言不同,Python 中像 a < b < c 这样的链式表达式具有传统的数学解释和优先级。
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
运算符 is 和 is not 测试的是对象的身份,而不是对象的_值_。
对象的身份在创建后永不改变,可以用 id() 函数获得。
当 且仅当 id(<apple>) == id(<orange>) 时,<apple> is <orange> 求值为 True。
<apple> is not <orange> 则得到相反的结果。
由于它们具有单例状态,None 和 NotImplemented 与条目比较时应该始终使用 is 和 is not。
关于这一约定的更多细节,请参阅 Python 参考文档中的值比较和 PEP8。
# A list of favorite numbers.
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and Python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
运算符 in 和 not in 测试的是_成员关系_。
如果 <fish> 是 <soup> 的成员(<fish> 是 <soup> 的子集,或被包含在 <soup> 中),<fish> in <soup> 求值为 True,否则求值为 False。
<fish> not in <soup> 返回相反的结果,也就是 <fish> in <soup> 的_反面_。
对于字符串和 bytes 类型,当且仅当 <name> 是 <fullname> 的子串时,<name> in <fullname> 为 True。
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe', 'id': 67826, 'age': 33, 'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
对象的比较行为可以通过实现 rich comparison methods 来定制。
更多信息请参阅 Python 教程:类、Python Classes and Magic Methods (Dan Bader)和特殊方法名。