【问题标题】:Accessing original int comparison from int-derived class with overloaded comparison operator使用重载的比较运算符从 int 派生类访问原始 int 比较
【发布时间】:2017-04-12 06:55:30
【问题描述】:

我有一个带有重载比较运算符的 int 派生类。

在重载方法的主体中,我需要使用原始运算符。

玩具示例:

>>> class Derived(int):
...     def __eq__(self, other):
...         return super(Derived, self).__eq__(other)

在 Python 3.3+ 上运行良好,但在 Python 2.7 上失败,异常 AttributeError: 'super' object has no attribute '__eq__'

我可以考虑几个步行区,我发现它们不是很干净:

return int(self) == other

需要创建一个新的 int 对象来比较它,而

try:
    return super(Derived, self).__eq__(other)
except AttributeError:
    return super(Derived, self).__cmp__(other) == 0

根据 Python 版本拆分控制流,我觉得这非常混乱(明确检查 Python 版本也是如此)。

如何在 Python 2.7 和 3.3+ 中以优雅的方式访问原始整数比较?

【问题讨论】:

  • 您可以通过super.__eq__ 访问int 比较方法。但是,根据 python 版本,内置类型比较方法的实现有很大不同。因此 python2 super.eq 需要 1 个参数(其他),而 python3 需要 2 个(自我和其他)
  • 你觉得int(self) == int(other)太乱了吗?
  • @Phillip 它比int(self) == other多了一个对象
  • @abukaj 啊,你已经考虑过了。对不起。我不认为你假设的开销是真实的。对于任何 Python 实现来说,如果不优化内置整数类型,那就太疯狂了,例如,really 每次你在某个地方有一个整数时都会实例化一个完整的对象。 (也就是说,在继续担心这种优化之前,我会做一些基准测试。)

标签: python python-2.7 inheritance operator-overloading comparison-operators


【解决方案1】:

Python 2 和 3 彼此之间有很大的不同,所以我认为你应该硬着头皮检查版本。如果您尝试编写适用于两者的代码(根据我的经验,迟早您会发现必须修补的东西),这只是可以预期的。为避免任何性能影响,您可以执行以下操作:

from six import PY2

class Derived(int):
    if PY2:
        def __eq__(self, other):
            return super(Derived, self).__cmp__(other) == 0
    else:
        def __eq__(self, other):
            return super(Derived, self).__eq__(other)

这就是我要做的。如果我真的想继承int...

如果你真的不想,也许你可以试试:

class Derived(int):
    def __eq__(self, other):
        return (self ^ other) == 0

显然,如果您关心性能,则必须对其余代码进行一些分析,并找出其中任何一个是否明显更差...

【讨论】:

  • 我喜欢后一种方法,但是当other 是浮点数时它不起作用
【解决方案2】:

我相信你应该在定义类之前在int 中定义__eq__。例如:

int = 5
def int.__eq__(self, other):
    return self.real == other
IntDerived = Derived(int)

这应该给super 类一个__eq__ 属性。


已编辑


主要想法有效,但我注意到代码不起作用。所以:改进的代码:

class Derived(int):
    def __eq__(self, other):
        return self.real == other

Int = 5
D = Derived(Int)
D.__eq__(4) #Output: False
D.__eq__(5) #Output: True

【讨论】:

  • 那不是 python。
  • @GreenHawk1220 如果您将__eq__() 方法放在Derived 类定义中(并使其在Python 中工作),我将接受答案。访问.real 属性的想法可行,但代码不是 Python。
  • 很高兴我能帮上忙。上帝保佑。
【解决方案3】:

使用 hasattr 可以避免创建新的 int 对象、捕获异常或显式检查 Python 版本。

以下代码适用于 Python 2.7 和 3.3+:

class Derived(int):
    def __eq__(self, other):
        return super(Derived, self).__cmp__(other) == 0 if hasattr(Derived, "__cmp__") else super(Derived, self).__eq__(other)

【讨论】:

    【解决方案4】:

    两个版本都实现了__xor__ 方法,你可以试试这个:

    class Derived(int):
        def __eq__(self, other):
            return not super(Derived, self).__xor__(other)
    

    【讨论】:

    • 我喜欢这个答案。不过,不是很干净,也不能与浮动比较。另外,我认为没有必要创建super 对象,self 就足够了。 self ^ other 可能更简单。
    猜你喜欢
    • 2020-11-10
    • 2020-01-21
    • 2018-12-23
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多