学习Python的__rand__()方法

383 阅读2分钟

句法

object.__rand__(self, other)

Python__rand__() 方法实现了反向的Bitwise AND *操作,其操作数被反射、交换。因此,当你调用x * y ,Python会尝试调用 [x.__and__(y)](https://blog.finxter.com/python-__and__/ "Python __and__() Magic Method").如果这个方法没有实现,Python 会尝试在右边的操作数上调用__rand__ ,如果这个方法也没有实现,它会引发一个TypeError

我们称这种方法为*"* Dunder Method",即*"Double UnderscoreMethod"(也叫"Magic Method")*。

背景 位数与 &

Python的位数与运算符对整数xy 的二进制表示中的每个位进行逻辑与运算。

因此,如果同一位置的两个输入位都是1,每个输出位就是1,否则就是0。

例如,整数表达式4&3被翻译成二进制的0100&0011,结果是0000,因为所有四个输入位的位置都不同。

在这个例子中,你将 位数与 操作符到两个整数 32 和 16。

>>> 32 & 16
0

表达式32 & 16 对位表示法"010000" (十进制 32) 和"001000" (十进制 16) 进行操作,并执行 位数与.由于所有第i个位的位置都不同,结果是0。

第一个操作数x100000
第二个操作数y010000
x & y000000

Python __and__ 与 __rand__ 的比较

假设,你想对两个自定义对象xy 进行& 计算。

print(x & y)

Python 首先尝试调用左边对象的__and__() 方法x.__and__(y) 。但这可能因为两个原因而失败。

  1. 方法x.__and__() 首先没有实现,或者
  2. 方法x.__and__() 已经实现,但是返回一个NotImplemented 值,表明数据类型不兼容。

如果失败了,Python 试图通过在右操作数上调用y.__rand__()反向位法和 方法来解决这个问题y

如果反向位数和方法被实现,Python 知道它不会遇到非交换性操作的潜在问题。如果它只是执行y.__and__(x) 而不是x.__and__(y) ,结果将是错误的,因为当定义为自定义操作时,该操作可能是非交换性的。这就是为什么需要y.__rand__(x)

因此,x.__and__(y)x.__rand__(y) 之间的区别是,前者计算x & y ,而后者计算y & x - 都是调用定义在对象x 上的各自方法。

你可以在这里看到这个效果,我们试图在左边的操作数x 上调用这个操作,但是由于它没有实现,Python 只是在右边的操作数y 上调用相反的操作。

class Data_1:
    pass

class Data_2:
    def __rand__(self, other):
        return 'called reverse bitwise AND'


x = Data_1()
y = Data_2()

print(x & y)
# called reverse bitwise XOR