语法
object.__xor__(self, other)
Python的__xor__() 方法实现了内置的Bitwise OR |操作。因此,当你调用x | y 时,Python 会尝试调用x.__or__(y) 。如果这个方法没有实现,Python首先尝试在右边的操作数上调用__ror__ ,如果这个方法也没有实现,就会引发一个TypeError 。
我们把这称为 "Dunder Method",即*"Double UnderscoreMethod"(也称为"Magic Method")*。
背景 位数OR |
Python的位数OR运算符x | y ,对整数x 和y 的二进制表示的每个位进行逻辑OR。当且仅当 同一位置上的两个输入位中至少有一个是1时,每个输出位才会被评估为1。例如,整数表达式4 | 3 被翻译成二进制运算0100 | 0011 ,结果是0111 ,因为对于最后三个位置,至少有一个位是1。
在这个例子中,你将 位数OR 操作符到两个整数32和16。
>>> 32 | 16
48
表达式32 | 16 对位表示法"010000" (十进制32)和"001000" (十进制16)进行操作,并执行 位数OR.每个"1" 的位置都会在结果"110000" (十进制48)中传播。
第一个操作数x | 1 | 0 | 0 | 0 | 0 | 0 |
第二个操作数y | 0 | 1 | 0 | 0 | 0 | 0 |
x | y | 1 | 1 | 0 | 0 | 0 | 0 |
例子 自定义__or__()
在下面的例子中,你创建了一个自定义类Data 并覆盖了__or__() 魔法方法,以便在试图计算位数OR操作时返回一个假字符串。
class Data:
def __or__(self, other):
return '... my result of OR ...'
a = Data()
b = Data()
print(a | b)
# ... my result of OR ...
如果你没有定义__or__() 方法,Python 会提出一个TypeError 。
TypeError: 不支持的操作数类型|
考虑一下下面的代码片段,你试图在没有定义dunder方法的情况下计算自定义对象的位数OR运算__or__() 。
class Data:
pass
a = Data()
b = Data()
print(a | b)
在我的电脑上运行这个导致了以下错误信息。
Traceback (most recent call last):
File "C:UsersxcentDesktopcode.py", line 8, in <module>
print(a | b)
TypeError: unsupported operand type(s) for |: 'Data' and 'Data'
这个错误的原因是,__or__() 方法从来没有被定义过--而且默认情况下没有为自定义对象定义该方法。所以,为了解决TypeError: unsupported operand type(s) for | ,你需要在你的类定义中提供__or__(self, other) 方法,如前所示。
class Data:
def __or__(self, other):
return '... my result of OR ...'
当然,在实践中你会使用另一个返回值,正如在**"背景 "**部分所解释的。
Python的__or__与__ror__
假设,你想对两个自定义对象x 和y 进行| 的计算。
print(x | y)
Python 首先尝试调用左边对象的__or__() 方法x.__or__(y) 。但这可能因为两个原因而失败。
- 该方法
x.__or__()首先没有实现,或者 - 该方法
x.__`or`__()已经实现,但返回一个NotImplemented,表明数据类型不兼容。
如果失败了,Python 试图通过调用右操作数的反向位法OR 的y.__ror__() 来解决这个问题y 。
如果逆向位数OR方法被实现了,Python知道它不会遇到非交换性操作的潜在问题。如果它只是执行y.__or__(x) 而不是x.__or__(y) ,结果将是错误的,因为当定义为自定义操作时,该操作可能是非交换性的。这就是为什么需要y.__ror__(x) 。
因此,x.__or__(y) 和x.__ror__(y) 之间的区别是,前者计算x | y ,而后者计算y | x - 两者都调用各自定义在对象x 上的方法。
你可以在这里看到这个效果,我们试图在左边的操作数x 上调用这个操作,但是由于它没有实现,Python 只是在右边的操作数y 上调用相反的操作。
class Data_1:
pass
class Data_2:
def __ror__(self, other):
return 'called reverse bitwise OR'
x = Data_1()
y = Data_2()
print(x | y)
# called reverse bitwise OR