python - 你能为 Python 中的重载运算符施加对象优先级吗?

标签 python operator-overloading operator-precedence

假设我有两个 Python 类,它们都定义了 add 和 radd 运算符重载,我将一个类的一个实例添加到另一个类的另一个实例。选择的实现取决于添加项目的顺序(Python 首先在 LHS 上寻找添加方法,等等)。

我是否可以定义一个优先级来决定优先使用哪个对象的实现?例如,如果 radd 的优先级高于 LHS,我希望在 RHS 上调用它。

我真的很想对所有重载运算符执行此操作,因此我最终寻求的是更通用的解决方案。

[编辑:添加示例]

例如,我可能有一个自定义数字类型类,我可能希望静默地将 int 类型转换为我的自定义类型。因此我需要 add 和 radd(以及所有其他运算符用它们的“r”表亲重载)。

接下来,我想要一个泛型多项式类,其系数是某种泛型数字类型。我还想将内容转换为多项式,因此我为它实现了 add 和 radd 函数。但是,如果我在左侧添加一个自定义数字,在右侧添加一个多项式,我希望它被向上类型转换为多项式,而不是 Python 试图将它向下类型转换> 自定义数字类型。因此,我希望调用 radd 而不是 add。

最佳答案

没有用于定义您所描述的“优先级”的内置机制。您可以做的是在魔术方法中自己实现优先级检查。也就是说,您可以定义该对象的 __add__ 方法,以便它检查另一个对象的“优先级”(无论如何定义),并调用该对象的 __add__(或 __radd__) 如果它的优先级更高。

请注意,如果您只想让 LHS __add__ 延迟到 RHS __radd__,您可以返回 NotImplemented,这实际上会告诉 Python “就好像您刚刚调用的 __add__ 方法不存在一样”。

下面是如何使用魔术方法上的装饰器完成此操作的草图:

def deco(op):
    def newOp(self, other):
        if other.precedence > self.precedence:
            return NotImplemented
        return op(self, other)
    return newOp

class Thing(object):
    precedence = 0

    def __init__(self, val):
        self.val = val

    @deco
    def __add__(self, other):
        print "Called", self, "__add__"
        return self.__class__(self.val + other.val)

    def __radd__(self, other):
        print "Called", self, "__radd__"
        return self.__class__(self.val + other.val)

class Weak(Thing):
    precedence = 1

class Strong(Thing):
    precedence = 2

这导致总是调用 Strong 版本,而不管操作数的顺序如何,所以它总是返回一个 Strong:

>>> Weak(1) + Strong(1)
Called <__main__.Strong object at 0x01F96BF0> __radd__
<__main__.Strong object at 0x01F96BD0>
>>> Strong(1) + Weak(1)
Called <__main__.Strong object at 0x01F96B90> __add__
<__main__.Strong object at 0x01F96250>

关于python - 你能为 Python 中的重载运算符施加对象优先级吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22289093/

相关文章:

python - Python OpenCV中的侵 eclipse 和膨胀返回白色

c++ - 高效运营商+

objective-c - 我可以在 Objective-C 中重载运算符吗?

c# - 逻辑 OR 和三元运算符求值顺序

parsing - 在Menhir/Ocamlyacc中为运算符(operator)指定动态优先级和优先级

php - php 中 "!print("1") || 1"的意外行为

python - 无法导入姓名

python - 通过python正则表达式忽略ip地址第一个八位字节中的这两个数字(以127或0开头)

python - 如何打印输出并保持在同一行(Python)?

c++ - 我不明白 std::shared_ptr 的 -> 运算符