Python魔法方法漫游指南:运算符

运算符魔法方法通常用于实现对象的运算、赋值等操作。

前言中介绍的 __add__ 就属于运算符魔法方法。让我们继续探讨。

比较运算符

使用 Python 魔法方法的一个巨大的好处,就是可以构建与内置类型相似行为的对象。

什么意思?比方说在某些语言中,要验证两个自定义对象是否相等,代码可能是这样:

if obj.isEqual(other):    # ...

Python 中同样可以这样实现,但缺点是它是非标准的,你可能需要稍微花一点时间才知道它要做什么。另外,不同的程序员可能对函数的名称理解不同,从而使得同一个功能具有 equals()isEqual()equalTo() 等不同的名称。

让我们看看如果运用了魔法方法:

if obj == other:    # ...

是不是一目了然?

要实现 == 运算符,只需要你实现 __eq__ 方法:

class Foo:    def __init__(self, id):        self.id = id            def __eq__(self, other):        return self.id == other.idf1 = Foo(1)f2 = Foo(1)f3 = Foo(2)print(f1 == f2, f2 == f3)# 输出:# True False

这就是魔法的力量。

类似的比较运算符还有:

  • __lt__
  • __le__
  • __ne__
  • __gt__
  • __ge__

分别实现 <<=!=>>= 运算符。

算数运算符

算数运算符用于常见的数学运算,如 + - * / 加减乘除等。

比如 __add__ 魔法方法可以实现加法操作。

整数相加的计算就相当于:

>>> num = 1>>> num + 23>>> num.__add__(2)3

你可以让一个自定义的类实现 __add__ 魔法方法,从而使它也可以进行加法计算。

比如定义一个矢量:

class Vector:    def __init__(self, x, y):        self.x = x        self.y = y            def __add__(self, other):        new_x = self.x + other.x        new_y = self.y + other.y        return Vector(new_x, new_y)

由于实现了 __add__ 方法,这个矢量类就可以非常自然的相加:

>>> v1 = Vector(1, 2)>>> v2 = Vector(3, 4)>>> v3 = v1 + v2>>> v3.x4>>> v3.y6

类似的,我们就可以实现 Vector 类的整套加减乘除运算了:

class Vector:    def __init__(self, x, y):        self.x = x        self.y = y            # 加    def __add__(self, other):        new_x = self.x + other.x        new_y = self.y + other.y        return Vector(new_x, new_y)    # 减    def __sub__(self, other):        new_x = self.x - other.x        new_y = self.y - other.y        return Vector(new_x, new_y)        # 乘    def __mul__(self, other):        new_x = self.x * other.x        new_y = self.y * other.y        return Vector(new_x, new_y)    # 除    def __truediv__(self, other):        new_x = self.x / other.x        new_y = self.y / other.y        return Vector(new_x, new_y)

类似的算数运算符还有:

  • __matmul__
  • __floordiv__
  • __mod__
  • __pow__
  • __lshift__
  • __rshift__
  • __and__
  • __xor__
  • __or__

以上魔法方法分别实现 @//%**<<>>&^| 操作。

了解这些方法的功能即可。需要用到时稍加搜索,就能知道其需要的参数。

除此之外还有个 __divmod__ 方法,它把除数和余数运算结果结合起来,返回一个包含商和余数的元组,也就是把 __floordiv____mod__ 的作用融合在一起了。

反算数运算符

上面探讨的算数运算符要求位于运算符前面的对象实现,比如:

first + second

这个式子中,要求 first 必须实现 __add__ 方法。

但是如果你没办法保证 first 的具体实现,那么也可以在 second 实现反算数运算符 __radd__,达到同样的效果。

应用场景举例:second 是库提供的,而 first 是用户自行编写,没办法保证其能够实现 __add__

反算数运算的名称就是在正常算数运算符前面加字母 r,比如 __radd____rsub__,就不展开讲了。

增量赋值符

与反算数运算符类似的还有增量赋值符,比如最常用的 +=

class Vector:    def __init__(self, x, y):        self.x = x        self.y = y        def __iadd__(self, other):        return Vector(self.x + other, self.y + other)v1 = Vector(-1, 2)v1 += 1print(v1.x, v1.y)# 输出:# 0 3

其他的增量赋值符的还有 __isub____imul__ 等,也不展开列举了。

一元运算符

一元运算符只有一个操作符。

还是拿上面的 Vector 类举例,比方说我要实现取负的操作:

class Vector:    def __neg__(self):        return Vector(-self.x, -self.y)        # 其他方法    # ...

那么就可以这样取负了:

>>> v1 = Vector(-1, 2)>>> v2 = -v1>>> print(v2.x, v2.y)1 -2

类似的一元运算符还有:

  • __pos__:取正,比如 +v1
  • __abs__:取绝对值,如 abs(v1)
  • __invert__:实现取反操作符 ~,二进制逐位取反。
  • __complex__:实现内建函数 complex(),取复数。
  • __int__:实现内建函数 int(),整型转换。
  • __float__:实现内建函数 float(),浮点数转换。
  • __round__:实现内建函数 round(),四舍五入。
  • __ceil__:实现内建函数 math.ceil(),大于原始值的最小整数。
  • __floor__:实现内建函数 math.floor(),小于原始值的最大整数
  • __trunc__:实现内建函数 math.trunc(),朝零取整
  • __index__:作为列表索引的数字。

稍微难理解的只有最后这个 __index__,用一个例子说明:

class Index:    def __index__(self):        return 1my_list = [0, 1, 2]    index = Index()print(my_list[index])# 输出:# 1

总结

以上就是常见运算符魔法方法的用法了。

可能你觉得实现个加减乘除没多大用处。别急,这只是魔法方法中非常小的一部分。让我们下一章继续深入。


本系列文章开源发布于 Github,传送门:Python魔法方法漫游指南

看完文章想吐槽?欢迎来 Issues 告诉我。


Python魔法方法漫游指南:运算符

Python魔法方法漫游指南:运算符

原文链接:,转发请注明来源!
「Python魔法方法漫游指南:运算符」评论列表

发表评论