Python 中的神秘运算符

简介: 此种情况下,__add__ 函数会被调用,self 对应的是 a 变量,而 value 对应的则是 b 变量。

今天我们来讲讲 Python 里一个不为众人所知的运算符。你可能会觉得疑惑:还有我不知道的运算符?别急着下结论,先往下看看再说。

在 Python3.5 中通过 PEP465

https://www.python.org/dev/peps/pep-0465加入了 @运算符,也就是矩阵相乘运算符。虽然目前没有任何内置的 Python 类型实现了这个运算符的逻辑(就只是挖了个坑),但是如果你用过 numpy,大概对这个运算符的逻辑并不陌生:


>>> a = numpy.array([1, 2, 3])
>>> b = numpy.array([10, 20, 30])
>>> a @ b
140
>>> c = numpy.array([[10, 15], [20, 25], [30, 35]])
>>> d = numpy.array([[4, 5, 6], [7, 8, 9]])
>>> c @ d
array([[145, 170, 195],
       [255, 300, 345],
       [365, 430, 495]])

如今,在原生的 Python 代码中,你也可以使用这个运算符。但前提是,你得自己实现具体的运算规则,也就是实现 __matmul__()__rmatmul__() __imatmul__() 这3个方法。

在看实例之前,我们先来了解下这种特殊的类方法。

在官方文档中,我们看到与 __matmul__ 方法一起介绍的还有 __add____sub__ 等等(注意前后都是2个下划线),这些方法都是用来定义此类型的运算符号。

假设现在有一个类叫 A,我们在其 class 中实现了加法方法 __add__

def __add__(self, value):    
# 具体实现代码(略)

那么我们就可以在代码中对 A 的实例进行加法运算:

a = A()
b = A()
c = a + b

此种情况下,__add__ 函数会被调用,self 对应的是 a 变量,而 value 对应的则是 b 变量。

__matmul__ 与之类似,唯一的不同就是它会在使用 @ 操作符而不是 + 时被调用。

同样的道理,__rmatmul__ 对应操作数不支持相关运算或者类型不同的情况,__imatmul__ 则对应复合赋值运算符的情况:


a = A()
b = A()
c = a @ b  # __matmul__
d = a @ 1  # __rmatmul__
a @= 1  #__imatmul__


接下来我们来创建一个继承 list 的类并实现矩阵乘法:


class NewList(list):
    def __matmul__(self, v):
        result = []
        for i in range(len(self)):
            result.append([])
            for j in range(len(v[0])):
                result[i].append(0)
        for i in range(len(self)):
            for j in range(len(v[0])):
                for k in range(len(v)):
                    result[i][j] += self[i][k] * v[k][j]
        return result
# 测试
x = NewList([[7, 7, 3],
    [4, 5, 6],
    [6, 4, 3]])
y = NewList([[5, 4, 1, 2],
    [6, 2, 3, 0],
    [4, 5, 6, 1]])
z = x @ y
for i in z:
    print(i)

输出结果:

[89, 57, 46, 17]
[74, 56, 55, 14]
[66, 47, 36, 15]

虽然这个符号的设定是用于矩阵乘法,但实际上可以自定义为任何操作。比如我们可以用它来计算直角坐标系上两个点之间的距离


from math import sqrt
class Point:
    def __init__(self, x, y):
        self.x = x   # x坐标
        self.y = y   # y坐标
    def __matmul__(self, value):
        x_sub = self.x - value.x
        y_sub = self.y - value.y
        return sqrt(x_sub**2 + y_sub**2)
a = Point(1, 3)
b = Point(4, 7)
print(a @ b)

以上便是我今天跟大家分享的 Python 神秘操作符。

注:本文来自编程教室的读者 @pynickle 即将发布的 GitChat 的一部分。此次 GitChat 中,他将会介绍一些 Python 的冷知识(但不适合零基础小白,明天截止预订),如果你感兴趣的话,欢迎加入一起讨论交流。

(点击文末 阅读原文 可直达)

作者:pynickle

相关文章
|
1月前
|
Python
python一元运算符的应用
【4月更文挑战第12天】Python的一元运算符包括正号(+), 负号(-), 按位取反(~), 取绝对值(abs())和类型转换(int(), float(), str())。例如:`+a`使数值变正,`-a`变为负数,`~a`为按位取反,`abs(a)`获取绝对值,而`int(a)`, `float(a)`, `str(a)`则用于类型转换。示例代码展示了这些运算符的使用效果。
19 0
|
1天前
|
Python
【Python操作基础】——运算符
【Python操作基础】——运算符
|
14天前
|
存储 运维 算法
python运算符详解(二)
python运算符详解(二)
|
14天前
|
Python 容器
python运算符详解(一)
python运算符详解(一)
|
18天前
|
运维 Shell Python
第四章 Python运算符与流程控制
第四章 Python运算符与流程控制
|
19天前
|
JSON 数据格式 索引
python 又一个点运算符操作的字典库:Munch
python 又一个点运算符操作的字典库:Munch
34 0
|
19天前
|
Python
Python运算符
Python运算符
7 0
|
19天前
|
JSON 数据处理 数据格式
python 一个点运算符操作的字典库:DottedDict
python 一个点运算符操作的字典库:DottedDict
14 0
|
25天前
|
开发者 索引 Python
Python中的海象运算符:简洁而强大的赋值表达式
【4月更文挑战第17天】Python 3.8 引入了海象运算符 `:=`,也称赋值表达式运算符,用于在表达式内部赋值,简化代码并提升可读性。它能用于条件判断、循环控制和函数参数等场景,优化逻辑流程。然而,使用时需注意可读性、运算符优先级及赋值限制,以确保代码清晰易懂。海象运算符是Python编程的一个有用工具,但应根据情况谨慎使用。
|
26天前
02-python的基础语法-标识符/运算符/字符串拓展/字符串的拼接/字符串格式化/字符串精度控制/字符串格式化方式2/对表达式进行格式化/练习题/数据输入-input语句
02-python的基础语法-标识符/运算符/字符串拓展/字符串的拼接/字符串格式化/字符串精度控制/字符串格式化方式2/对表达式进行格式化/练习题/数据输入-input语句