【python】魔术方法大全(五)——运算篇

今天我们来聊聊魔术方法使用的精髓,叫做emulation。我们知道python中的类型系统叫做duck type。

简单的说,就是他不去检查具体的这个对象是什么类型,而是检查这个对象有没有相应的功能。

而python中有大量的魔术方法,就是给某一个对象加上相应的功能,接下来聊一聊emulating numeric types,也就是让你的类型实现一些数的功能。

__add__魔术方法

__add__是一种在Python中定义对象之间加法操作的魔术方法。当使用“+”运算符对两个对象执行加法操作时,Python将会查找并调用每个对象中定义的__add__方法。

以下是一个简单的例子,其中我们定义了一个名为MyNumber的类,并定义了__add__方法来允许在对象之间执行加法操作:


class MyNumber:
    def __init__(self, value):
        self.value = value

    def __add__(self, other):
        if isinstance(other, MyNumber):
            return MyNumber(self.value + other.value)
        elif isinstance(other, (int, float)):
            return MyNumber(self.value + other)
        else:
            return NotImplemented

    def __repr__(self):
        return f"MyNumber({self.value})"

n1 = MyNumber(1)
n2 = MyNumber(2)
print(n1 + n2)
print(n1 + 5)
print(n2 + "3")

输出结果为:

Traceback (most recent call last):
  File "/mnt/f/lianhaifeng_codes/djangoProject/djangoProject/sss.py", line 21, in <module>
    print(n2 + "3")
TypeError: unsupported operand type(s) for +: 'MyNumber' and 'str'
MyNumber(3)
MyNumber(6)

__iadd__魔术方法

__iadd__是Python中的一个魔术方法,用于在类中定义就地加法的实现,即将两个对象相加,并将结果存储在第一个对象中。在Python中,就地加法使用+=运算符进行实现,如果类中没有实现__iadd__,则Python解释器会尝试使用__add__方法代替__iadd__方法,这样会创建一个新的对象并返回结果。

以下是一个使用__iadd__方法的示例:

class MyList:
    def __init__(self, items):
        self.items = items

    def __iadd__(self, other):
        if isinstance(other, MyList):
            self.items.extend(other.items)
        else:
            self.items.append(other)
        return self

    def __repr__(self):
        return f'MyList({self.items})'

l1 = MyList([1, 2, 3])
l2 = MyList([4, 5, 6])
l1 += l2  # 就地加法
print(l1)  # 输出 MyList([1, 2, 3, 4, 5, 6])

在上面的示例中,MyList类实现了__iadd__方法,用于将两个MyList对象进行就地加法。当执行l1 += l2时,l1对象的__iadd__方法被调用,将l2对象的内容添加到l1中,最终结果存储在l1中。

需要注意的是,__iadd__方法需要返回self对象,以便在就地加法完成后继续使用当前对象。

__sub__魔术方法

__sub__是一个魔术方法,用于定义两个对象相减的行为。当对象使用 - 运算符进行相减操作时,会自动调用 __sub__ 方法。

下面是一个例子,展示了如何定义一个自定义对象的 __sub__ 方法:

class MyNumber:
    def __init__(self, value):
        self.value = value

    def __sub__(self, other):
        return MyNumber(self.value - other.value)

    def __repr__(self):
        return f"MyNumber({self.value})"

a = MyNumber(10)
b = MyNumber(5)
c = a - b
print(c)  # 输出 MyNumber(5)

__mul__魔术方法

__mul__是Python中的一个魔术方法,用于在两个对象相乘时调用。它接受两个参数:selfother,其中self是调用方法的对象,而other是传递给方法的参数。

下面是一个简单的例子,展示了如何使用__mul__方法重载乘法运算符:

class MyClass:
    def __init__(self, value):
        self.value = value
    
    def __mul__(self, other):
        return MyClass(self.value * other)

x = MyClass(10)
y = x * 2
print(y.value)  # 输出 20

__rmul__魔术方法

__rmul__魔术方法是指右侧乘法运算的魔术方法。当一个对象被用于乘法运算并且它是另一个对象的右侧操作数时,Python会尝试调用它的__rmul__方法来进行运算。

例如,在下面的代码中,我们创建了一个自定义的类MyInt,它包含一个整数值,并实现了__rmul__方法:

class MyInt:
    def __init__(self, value):
        self.value = value
    
    def __rmul__(self, other):
        return MyInt(self.value * other)

x = MyInt(10)
result = 5 * x
print(result.value)  # 输出 50

在上面的例子中,Python首先将5作为参数传递给__rmul__方法,因此other参数的值为5。__rmul__方法将MyInt对象的值与other参数相乘,并返回一个新的MyInt对象,其值为乘积。最后,结果被赋给result变量,并打印出来。

需要注意的是,在__rmul__方法中,我们必须返回一个新的对象,而不能修改原始对象的值。这是因为Python的乘法运算符是不可变的,所以我们不能直接在原始对象上修改它的值。

__matmul__魔术方法

__matmul__是一个魔术方法,用于定义对象的“@”运算符。当我们使用“@”运算符时,Python 会自动调用该对象的__matmul__方法。

例如,我们可以定义一个Matrix类,并在其中实现__matmul__方法来定义矩阵相乘的操作。以下是一个简单的示例:

class Matrix:
    def __init__(self, data):
        self.data = data
    
    def __matmul__(self, other):
        if not isinstance(other, Matrix):
            raise TypeError('Operand must be a matrix')
        if len(self.data[0]) != len(other.data):
            raise ValueError('Matrix dimensions do not match')
        result = [[0] * len(other.data[0]) for _ in range(len(self.data))]
        for i in range(len(self.data)):
            for j in range(len(other.data[0])):
                for k in range(len(other.data)):
                    result[i][j] += self.data[i][k] * other.data[k][j]
        return Matrix(result)
        
m1 = Matrix([[1, 2], [3, 4]])
m2 = Matrix([[5, 6], [7, 8]])
result = m1 @ m2
print(result.data) # 输出 [[19, 22], [43, 50]]

在这个例子中,Matrix类具有一个属性data,它是一个二维列表,代表矩阵中的数据。__matmul__方法接受另一个Matrix对象作为参数,并计算它们的矩阵乘积。

在这个例子中,我们首先创建了两个矩阵m1m2,然后使用@运算符将它们相乘,并将结果存储在变量result中。最后,我们打印了结果矩阵的数据。

__truediv__魔术方法

__truediv__是Python中的一个魔术方法,用于实现对象除法运算。当使用“/”符号时,会自动调用该方法。需要注意的是ÿ

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值