我无意中输入了time.clock<()
,其中Python 2.7解释器响应为:True
。以下代码举例说明了该行为:
>>> repr(time.clock)
'<built-in function clock>'
>>> time.clock<()
True
此外:
>>> import sys
>>> sys.maxint < ()
True
>>> map(lambda _:0<_,((),[],{}))
[True, True, True]
相反:
>>> 1<set(())
TypeError: can only compare to a set
问题:除了原因之外,空的list
,tuple
或dict
评估的实际意义或目的是否大于任何数字?
更新 :
Viktor 指出默认情况下会比较内存地址:
>>> map(lambda _:(id(0),'<',id(_)),((),[],{}, set([])))
[(31185488L, '<', 30769224L), (31185488L, '<', 277144584L), (31185488L, '<',
279477880L), (31185488L, '<', 278789256L)]
尽管看似顺序,这是不正确的。
如果没有定义明确的比较运算符,Python 2会比较 数字和类型名称,数字具有最低优先级。
这并未暗示正在调用的内部方法。另请参阅此内容,但有用inconclusive SO thread:
在IPython 2.7.5 REPL中
>>> type(type(()).__name__)
Out[15]: str
>>> type(()) < 10
Out[8]: False
>>> 10 < type(())
Out[11]: True
#as described
>>> type(()) < type(())
Out[9]: False
>>> type(()) == type(())
Out[10]: True
However:
>>> 'somestr' .__le__(10)
Out[20]: NotImplemented
>>> 'somestr' .__lt__(10)
Out[21]: NotImplemented
>>> int.__gt__
Out[25]: <method-wrapper '__gt__' of type object at 0x1E221000>
>>> int.__lt__
Out[26]: <method-wrapper '__lt__' of type object at 0x1E221000>
>>> int.__lt__(None)
Out[27]: NotImplemented
#.....type(...), dir(...), type, dir......
#An 'int' instance does not have an < operator defined
>>> 0 .__lt__
Out[28]: AttributeError: 'int' object has no attribute '__lt__'
#int is actually a subclass of bool
>>>int.__subclasses__()
Out: [bool]
#str as the fallback type for default comparisons
>>> type(''.__subclasshook__)
Out[72]: builtin_function_or_method
>>> dir(''.__subclasshook__)
Out[73]:
['__call__',
'__class__',
'__cmp__',
'__delattr__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__lt__',
'__module__',
'__name__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__self__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__']
#IPython is subclassing 'str'
>>> str.__subclasses__()
Out[84]: [IPython.utils.text.LSString]
答案 0 :(得分:5)
在Python 2中,当比较不同的类型时,python会在其他所有类型之前对数字类型进行排序,并在其余排序类型之间按类型名称进行排序。
因此,整数在元组之前排序,但类Foo
的实例将在类Bar
的实例之后对进行排序。
Python 3消除了这种疯狂;比较不同的类型会导致TypeError:
>>> 10 < ()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < tuple()
Python set()
类型通过实现__gt__
或'大于'魔术方法重载了>
运算符;它被调用1 < set()
表达式,因为int
类型没有__lt__
,低于 - 然后Python在这种情况下测试反向;毕竟,如果x < y
为真,y > x
为真。
当另一个操作数不是set.__gt__()
时,TypeError
挂钩会引发set
:
>>> 1 .__lt__(set())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__lt__'
>>> set().__gt__(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only compare to a set
用于集合的重载>
(大于)运算符用于测试左侧操作数是否为proper superset of the right-hand operand。 (从技术上讲,set
个对象实现了C-API PyTypeObject.tp_richcompare
函数,而不是直接__gt__
挂钩,但__gt__
挂钩转换为tp_richcompare
调用案例自动)。
当重载的比较方法(.__lt__()
, .__le__()
, .__eq__()
, . __ne__()
, . __gt__()
, . __ge__()
, or . __cmp__()
之一)返回NotImplemented
单例对象时,这表示不支持比较,Python回退到默认行为。正如How do Python comparison operators < and > work with a function name as an operand?中所述,此默认行为在Python 2和3之间有所不同。
对于Python 3,返回NotImplemented
的比较挂钩会导致Python引发TypeError
:
>>> class Foo():
... def __lt__(self, other): return NotImplemented
...
>>> Foo() < Foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: Foo() < Foo()
Python 2更顽固,当返回NotImplemented
或没有实现挂钩时,C代码最终会出现在default_3way_compare()
C function中,其中:
None
(第780-783行)PyNumber_Check
测试将类型名称设置为空,第786-793行)v->ob_type->tp_name
和w->ob_type->tp_name
在第786-793行)