Python 魔法方法2

本文介绍了Python中与运算相关的魔法方法,如__add__,__radd__,并通过示例解释了它们在自定义类型中的使用,特别是如何重写这些方法来自定义对象的行为。文章还提到了增强赋值运算的魔法方法,如__iadd__,并讨论了在不同对象类型组合时这些方法的调用规则。
摘要由CSDN通过智能技术生成

        基础的魔法方法在下面这篇文章有介绍。 

基础魔法方法https://blog.csdn.net/qq_49873907/article/details/130230106?spm=1001.2014.3001.5501       

         这篇文章主要介绍一下Python与运算相关的魔法方法会挑选择几个经典的方法来详细说明。

一、与运算相关的魔法方法

1.1 算术运算

        与算数运算有关的魔法方法如下表: 

算术运算的魔法方法
魔法方法行为
__add__(self, other)定义加法的行为 : +
__sub__(self, other)定义减法的行为 : -
__mul__(self, other)定义乘法的行为:*
__truediv__(self, other)定义真除法的行为 : /
__floordiv__(self, other)定义整数除法的行为 : //
__mod__(self, other)定义取模算法的行为:%
__divmod__(self, other)定义当被 divmod0 调用时的行为
__pow__(self, otherl modulo])定义当被 power0 调用或 ** 运算时的行为
__Ishift__(self, other)定义按位左移位的行为 :<<
__rshift__(self, other)定义按位右移位的行为 :>>
__and__(self,other)定义按位与操作的行为 :&
__xor__(self, other)定义按位异或操作的行为 :^
__or__(self, other)定义按位或操作的行为 :|

1.1.1 __add__(self, other)

        对于上述表格中的一些算数相关的魔法方法,使用的方式都是一样的,我们选择__add__(self, other)来进行简单的介绍。

        对于这些方法我们可以改变原有的功能,自定义魔法方法,举个例子:比如__add__(self, other)是用来拼接两个字符串,我们可以对其进行修改,用自己的方法去覆盖Python中默认的方法,当触发加法操作的时候,进行字符串长度的求和。

class A(str):           #继承str类,str类中有多种关于字符串的操作函数
	def __add__(self,other):    #重写__add__()方法
		return len(self)+len(other)  #定义方法功能为计算字符串的长度

	
a1 = A("hello")  #创建实例对象a1
a2 = A("world")  #创建实例对象a2
a1+a2            #输出a1+a2的结果

# 10

        这里我们得到了 ‘hello’ + ‘world’ 字符串的长度——10,而不是拼接后的字符串‘helloworld’,因为我们对其进行了拦截,检测到加法操作的时候去执行了我们定义的功能。

        我们知道,对于加法操作要有两个对象才行,那么我们重写的__add__()方法是属于‘+’前面的对象还是后面的对象呢?我们来简单测试一下:

class A(str):
	def __add__(self,other):
		return len(self)+len(other)

a1 = A("hello")
a2 = A("world")


a1+"world"    
# 10 
"hello" +a2
# 'helloworld'

        通过结果我们可以看出,重写的__add__()方法是属于‘+’前面的对象,其实这样的写法就相当于a1[self].__add__(a2[other])。对于其他与算数运算相关的魔法方法也是类似的用法,这里不再一一举例。

1.2 反算数运算

        与反算数运算有关的魔法方法如下表: 

与反运算相关的魔法方法
魔法方法行为
__radd__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rsub__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rmul__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rtruediv__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rfloordiv__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rmod__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rdivmod__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rpow__(self, otherl modulo])( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rIshift__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__vrshift__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__rxor__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)
__ror__(self, other)( 与算数运算相同,当左操作数不支持相应的操作时被调用)

       对于反算数运算方法的调用前提是:对两个对象进行相关运算(比如加法运算),如果左侧的对象和右侧的对象是不同类型(不同类的对象),并且左侧的对象没有定义__add__()方法,或者是其__add__()方法返回 NotImplemented(没有实现)那么Python就会去右侧的对象中查找是否有__radd__()方法的定义。

1.2.1 __radd__(self, other)

        根据上述描述,我们定义一个加法操作来验证:

class A(str):
	def __add__(self,other):
		return NotImplemented  #返回NotImplemented  表示没有实现的功能

	
class B(str):
	def __radd__(self,other):  #定义__radd__(self,other)
		return len(self)+len(other) 

	
a = A("hello")
b = B("world")
a+b
# 10

        我们明明没有实现__add__()的功能,可是结果还是得到了字符串的长度,说明我们的__radd__() 方法起到了作用。

        这里一定要注意的两点是:

左侧和右侧的对象是不同类型

②左侧没有实现相应的魔法方法

        比如我们使用相同类型的对象进行运算:

class B(str):
	def __radd__(self,other):
		return len(self)+len(other)


b1 = B("haha")
b2 = B("yeye")
b1+b2

# 'hahayeye'

         由于b1和b2属于同一个类的对象,所以不会去使用__radd__()的方法,而会去调用父类中的字符串拼接方法。

1.3 增强赋值运算

与增强赋值运算有关的魔法方法如下:

与增强赋值运算相关的魔法方法
魔法方法行为
__iadd__(self, other)定义赋值加法的行为 : + =
__isub__(self, other)定义赋值减法的行为 : - =
__imul__(self, other)定义赋值乘法的行为:* =
__itruediv__(self, other)定义赋值真除法的行为 : / =
__ifloordiv__(self, other)定义赋值整数除法的行为 : // =
__imod__(self, other)定义赋值取模算法的行为:% =
__ipow__(self, otherl modulo])定义赋值幂运算时的行为:** =
__iIshift__(self, other)定义赋值按位左移位的行为 :<< =
__irshift__(self, other)定义赋值按位右移位的行为 :>> =
__iand__(self,other)定义赋值按位与操作的行为 :& =
__ixor__(self, other)定义赋值按位异或操作的行为 :^ =
__ior__(self, other)定义赋值按位或操作的行为 :| =

        所谓增强赋值运算,就是运算兼赋值的操作,也就是说s1+=s2相当于s1=s1.__iadd__(s2),

参数是s2这么个意思。增强运算会修改对象自身进行自我赋值。

1.3.1 __iadd__(self, other)

                

class S1(str):
	def __iadd__(self,other):
		return len(self)+len(other)

class S2(str):
	def __radd__(self,other):
		return len(self)+len(other)

	
s1 = S1("python")
s2 = S2("java")
s1 += s2   #出发赋值运算
s1

# 10

        对于增强赋值运算,如果运算符左边没有实现__iadd__(self, other)方法,那么python会去寻找__radd__(self, other)和__add__(self, other)方法。例如:

class S2(str):
	def __radd__(self,other):
		return len(self)+len(other)

	
ss = S2("111")
sss= S2("222")
ss += sss
ss


#'111222'

        上述代码中没有实现__iadd__(self, other)方法,但是也没有执行__radd__(self, other)的方法,这是为什么呢?因为我们创建的实例对象ss和sss属于同一个对象,而__radd__(self, other)触发的条件时来自不同类的对象,所以不会打印出字符串的长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学者山羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值