int() 对象如何在 python2 中使用没有 __eq__() 方法的“==”运算符?
How int() object uses "==" operator without __eq__() method in python2?
最近我阅读了 "Fluent python" 并了解 ==
运算符如何使用 __eq__()
方法与 python 对象一起工作。但是它如何与 python2 中的 int
个实例一起使用?
>>> a = 1
>>> b = 1
>>> a == b
True
>>> a.__eq__(b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__eq__'
在python3全部a.__eq__(b)
returnsTrue
在Python2中,int
对象使用了__cmp__()
方法,而不是__eq__()
、__lt__()
、[=14=等丰富的方法],以及其他。
Python prefers to use rich comparison functions(__eq__
、__lt__
、__ne__
等),但如果这些不存在,则返回到使用单个比较函数(__cmp__
,在 Python 3 中删除):
These are the so-called “rich comparison” methods, and are called for comparison operators in preference to __cmp__()
below.
Python 2 integer type没有实现丰富的比较功能:
PyTypeObject PyInt_Type = {
...
(cmpfunc)int_compare, /* tp_compare */
...
0, /* tp_richcompare */
在 Python 3 中,integer type(现在是 long)只实现了丰富的比较功能,因为 Python 3 放弃了对 __cmp__
的支持:
PyTypeObject PyLong_Type = {
...
long_richcompare, /* tp_richcompare */
这就是 (123).__eq__
不存在的原因。相反,Python 2 在测试两个整数是否相等时退回到 (123).__cmp__
:
>>> (1).__eq__(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__eq__'
>>> (1).__cmp__(2)
-1
这是我的答案。
import sys
SPECIAL_OPNAMES = \
{ '__eq__': (lambda *args, **kwargs: not cmp(*args, **kwargs)) \
, '__ne__': (lambda *args, **kwargs: cmp(*args, **kwargs)) \
, '__lt__': (lambda *args, **kwargs: cmp(*args, **kwargs) < 0) \
, '__ge__': (lambda *args, **kwargs: cmp(*args, **kwargs) >= 0) \
, '__gt__': (lambda *args, **kwargs: cmp(*args, **kwargs) > 0) \
, '__le__': (lambda *args, **kwargs: cmp(*args, **kwargs) <= 0) \
} if sys.version_info.major == 2 else \
{}
工作示例:
>>> item = 1
>>> opname = '__eq__'
>>> t = type(item)
>>> op = SPECIAL_OPNAMES[opname] if opname in SPECIAL_OPNAMES else getattr(t, opname)
>>> op(item, 1)
True
最近我阅读了 "Fluent python" 并了解 ==
运算符如何使用 __eq__()
方法与 python 对象一起工作。但是它如何与 python2 中的 int
个实例一起使用?
>>> a = 1
>>> b = 1
>>> a == b
True
>>> a.__eq__(b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__eq__'
在python3全部a.__eq__(b)
returnsTrue
在Python2中,int
对象使用了__cmp__()
方法,而不是__eq__()
、__lt__()
、[=14=等丰富的方法],以及其他。
Python prefers to use rich comparison functions(__eq__
、__lt__
、__ne__
等),但如果这些不存在,则返回到使用单个比较函数(__cmp__
,在 Python 3 中删除):
These are the so-called “rich comparison” methods, and are called for comparison operators in preference to
__cmp__()
below.
Python 2 integer type没有实现丰富的比较功能:
PyTypeObject PyInt_Type = {
...
(cmpfunc)int_compare, /* tp_compare */
...
0, /* tp_richcompare */
在 Python 3 中,integer type(现在是 long)只实现了丰富的比较功能,因为 Python 3 放弃了对 __cmp__
的支持:
PyTypeObject PyLong_Type = {
...
long_richcompare, /* tp_richcompare */
这就是 (123).__eq__
不存在的原因。相反,Python 2 在测试两个整数是否相等时退回到 (123).__cmp__
:
>>> (1).__eq__(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__eq__'
>>> (1).__cmp__(2)
-1
这是我的答案。
import sys
SPECIAL_OPNAMES = \
{ '__eq__': (lambda *args, **kwargs: not cmp(*args, **kwargs)) \
, '__ne__': (lambda *args, **kwargs: cmp(*args, **kwargs)) \
, '__lt__': (lambda *args, **kwargs: cmp(*args, **kwargs) < 0) \
, '__ge__': (lambda *args, **kwargs: cmp(*args, **kwargs) >= 0) \
, '__gt__': (lambda *args, **kwargs: cmp(*args, **kwargs) > 0) \
, '__le__': (lambda *args, **kwargs: cmp(*args, **kwargs) <= 0) \
} if sys.version_info.major == 2 else \
{}
工作示例:
>>> item = 1
>>> opname = '__eq__'
>>> t = type(item)
>>> op = SPECIAL_OPNAMES[opname] if opname in SPECIAL_OPNAMES else getattr(t, opname)
>>> op(item, 1)
True