Python 字典中 “<” 的含义是什么?
我注意到Python允许我这样做:
>>> {1: "foo"} < {2: "bar"}
True
它也允许我对列表、双端队列等做同样的事情。那么在Python中,<
这个符号在字典上有什么特别的含义呢?
一般来说,我在哪里可以找到关于<
在任何集合类型上的含义呢?大多数情况下,这似乎在文档中找不到。例如:
>>> help(dict.__cmp__)
Help on wrapper_descriptor:
__cmp__(...)
x.__cmp__(y) <==> cmp(x,y)
>>> help(cmp)
Help on built-in function cmp in module __builtin__:
cmp(...)
cmp(x, y) -> integer
Return negative if x<y, zero if x==y, positive if x>y.
我问这个是因为我有一个元组列表,格式是(int, dict)
。我想根据第一个元素对这个数组进行排序,但如果两个项目的第一个元素相同,我就不在乎第二个元素。我想知道myArray.sort()
在这种情况下是否会做一些复杂的事情,比如递归遍历字典,还是说它只是返回一个任意的值。
2 个回答
就像@thefourtheye的回答那样。
用Python写的,可以这样理解:
def dict_compare(a, b):
if len(a) != len(b): # STEP 1: compare by length
return -1 if len(a) < len(b) else 1
res = 0
akey, aval = characterize(a, b) # Find first k, v that a[k] != b[k]
bkey, bval = characterize(b, a)
if akey is None: # if no difference
return 0
if bkey is not None: # STEP 2: compare by key
res = cmp(akey, bkey)
if res == 0 and bval is not None: # STEP 3: compare by value
res = cmp(aval, bval)
return res
其中,characterize
这个函数大概是这样的:
def characterize(a, b):
"""Find the first k that a[k] != b[k]"""
akey, aval = None, None
for k, v in a.items():
if akey < k:
continue
if (k not in b) or (a != b[k]):
akey, aval = k, v
return akey, aval
引用自比较文档,
元组和列表
元组和列表的比较是通过比较它们对应的元素来进行的。这意味着要想两个序列相等,每个元素都必须相等,并且这两个序列必须是同一种类型且长度相同。
如果不相等,那么它们的顺序是根据第一个不同的元素来决定的。例如,比较[1,2,x]和[1,2,y]的结果和比较x和y的结果是一样的。如果对应的元素不存在,较短的序列会排在前面(比如说,[1,2] < [1,2,3])。
字典
字典只有在它们的排序后的(键,值)列表相等时才算相等。(这个实现方式很高效,不需要构建列表或排序。)除了相等的结果外,其他结果会一致处理,但没有其他定义。(早期版本的Python [在2.7.6之前]使用排序后的(键,值)列表进行字典的字典序比较,但这在比较相等时开销很大。更早的版本仅通过身份比较字典,但这让人感到意外,因为人们期望能通过与{}比较来测试字典是否为空。)
另外,可以查看文档中的这一部分,专门讲了序列类型之间以及与其他类型的比较,
序列对象可以与其他相同类型的对象进行比较。比较是通过字典序进行的:首先比较前两个元素,如果它们不同,就决定了比较的结果;如果相等,就比较下两个元素,依此类推,直到其中一个序列比较完。如果要比较的两个元素本身也是相同类型的序列,则会递归进行字典序比较。如果两个序列的所有元素都相等,则这两个序列被认为是相等的。如果一个序列是另一个序列的初始子序列,则较短的序列被认为是较小的(更小的)序列。字符串的字典序比较使用的是字符的ASCII顺序。
需要注意的是,比较不同类型的对象是合法的。结果是确定的,但任意的:类型是按名称排序的。因此,列表总是小于字符串,字符串总是小于元组,等等。(不同类型对象的比较规则不应被依赖;它们可能会在未来的语言版本中发生变化。)混合数字类型的比较是根据它们的数值进行的,所以0等于0.0,等等。
根据Python 2.7源代码,实际的字典比较过程如下:
首先比较键的长度。(如果第一个字典的键更少,返回
-1
;如果第二个字典的键更少,返回1
)如果长度相同,就尝试找一个键,看看在另一个字典中是否缺少这个键或者这个键的值不同(这叫做描述字典)
执行第2步,无论是还是
b, a
。如果其中一个字典是空的,那么两个字典被认为是相等的。现在,从描述字典中得到的差异将被比较,以得出实际的比较结果。