【问题标题】:How int() object uses "==" operator without __eq__() method in python2?int() 对象如何在 python2 中使用没有 __eq__() 方法的“==”运算符?
【发布时间】:2016-08-23 14:59:14
【问题描述】:

最近我阅读了“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)返回True

【问题讨论】:

  • stackoverflow.com/questions/3588776/… 看看这里的几个答案,我认为他们解释得很好
  • 大胆猜测,但from operator import eq; eq(2,2) 在 Python2 中确实有效。或者使用__cmp__
  • a.__cmp__ 存在,这可能是 Python 2 正在使用的。

标签: python python-2.7 python-internals


【解决方案1】:

Python prefers to use rich comparison functions__eq____lt____ne__ 等),但如果这些不存在,则回退到使用单个比较函数(__cmp__,在 Python 3 中删除):

这些就是所谓的“富比较”方法,比较运算符优先于下面的__cmp__()调用。

Python 2 integer type 没有实现丰富的比较功能:

PyTypeObject PyInt_Type = {
    ...
    (cmpfunc)int_compare,                       /* tp_compare */
    ...
    0,                                          /* tp_richcompare */

在 Python 3 中,integer type(现在很长)只实现了丰富的比较函数,因为 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

【讨论】:

    【解决方案2】:

    在 Python 2 中,int 对象使用 __cmp__() 方法,而不是像 __eq__()__lt__()__gt__() 等丰富的方法。

    【讨论】:

    • 你怎么知道的?您在文档中有参考,还是...?
    • 您可以通过在 Python 中运行 dir(int_instance) 来检查这一点;没有可用的__eq__ 方法。您可以阅读更多关于 __cmp__() 与富运营商 here. 的信息
    【解决方案3】:

    这是我的答案。

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-15
      • 2016-01-03
      • 1970-01-01
      • 2016-09-19
      • 2018-08-16
      • 2023-04-08
      • 2015-10-04
      相关资源
      最近更新 更多