Python的 __rlshift__() 方法

316 阅读1分钟

语法

object.__rlshift__(self, other)

Python__rlshift__() 方法实现了 逆时针左移操作反映,交换了操作数。因此,当你调用x << y 时,Python 会尝试调用 [x.__lshift__(y)](https://blog.finxter.com/python-__lshift__/ "Python __lshift__() Magic Method").如果这个方法没有实现,Python 会尝试在右边的操作数上调用y.__rlshift__(x) ,如果这个方法也没有实现,它就会引发一个TypeError

__rlshift__() 方法在实践中经常被用来为一个还没有提供左移功能的类添加左移功能,该类不能被修改,比如一个列表或内置数据类型。通过为另一个操作数实现这个方法,你仍然可以为没有实现__lshift__() 的类使用左移功能。

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

背景位数左移

Python的__lshift__() 方法实现了内置的<< 操作。因此,当你调用x << y 时,Python 会尝试调用x.__lshift__(y)

对于一个正整数,它在右边插入一个0 位,并将所有剩余的位向左移动一个位置。例如,如果你把二进制表示法0101 左移一个位置,你会得到01010 。从语义上讲,比特左移操作符x << n ,相当于整数x2**n 相乘。

print(8 << 1)
# 16

print(8 << 2)
# 32

print(-3 << 1)
# -6

Python的__lshift__与__rlshift__对比

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

print(x << y)

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

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

如果失败了,Python 试图通过调用y.__rlshift__() 对右操作数进行反向左移来 解决这个问题y 。并不是说这与>运算符">右移不一样,它只是意味着在第二个操作数上调用左移操作y

如果实现了反向左移的方法,Python 知道它不会遇到非交换性操作的潜在问题。如果它只是执行y.__lshift__(x) 而不是x.__lshift__(y) ,结果就会是错误的,因为这个操作是非交换性的。这就是为什么需要y.__rlshift__(x)

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

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

class Data_1:
    pass

class Data_2:
    def __rlshift__(self, other):
        return 'called reverse lshift'


x = Data_1()
y = Data_2()

print(x << y)
# called reverse lshift