"2" < 1 == True

python_compare

Python 语言中, 不同类型对象之间的比较规则浅析

今天为了捉一个臭虫耗废了近一个小时,最后发现是 if foo > 1:这里的foo实际是字符串,导致foo"0"时,"0" > 1为真。于是便花了点时间研究了下Python比较运算规则。

Python2中,比较运算遵循以下规则:

  1. 数字和数字按大小排序 (数字类型包括 int, float, long, complex, bool
  2. 字符串按字符串按字典序排序(str, unicode)
  3. 数字类型和非数字类型比较,除None外,数字类型总是小于非数字类型。
  4. 两个非数字不同类型,按其类型名的字典与排序
  5. 第4点有一个特例,老式类的实例总是小于新式类
  6. 非数字/字符串类型的同一类型的不同实例的比较,如果类定义了__cmp__()方法,则用该方法比较
  7. 同上,若类型没定义__cmp__()方法, 则按实例在内存中的地址排序
  8. None < None
  9. 3,4,5,7 是CPython的实现,不是Python语言自身的标准,参见[CPython implementation detail][]。 Python语言只要求对非数字和字符串类型的不同对象的比较,总是不想等的,比较结果可以是任意的,但必须是一致的(即多次比较,结果恒定)。

Python3终于修了这个bug ( What’s New In Python 3.0 ), 规则如下:

  1. incomparable类型对象比较 \<, \<=, >=, > 会 raise TypeError
  2. incomparable类型对象比较 !=, == 仍是合法的,但总为False
  3. cmp()__cmp__()方法被弃置了,取而代之的是__lt__()__eq__()__hash__() ...

Python2 当初会设计这种比较规则,可能是为了便于对包含不同类型对象的容器排序。list.sort()sorted()都仿照了C/C++里的sortPython2.4sort使用key来比较不同对象显然更Pythonic

更多例子,参见Sorting Mini-HOW TO