我是靠谱客的博主 高高纸飞机,最近开发中收集的这篇文章主要介绍python 魔法方法加减乘除_python魔法方法-反射运算和增量运算,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

反射运算

什么是反射运算符,其实就是反转了两个对象,下面先看一个普通运行符的实现:

classFoo(object):def __init__(self, x):

self.x=xdef __add__(self, other):return 'Foo:%s + %s' %(self.x, other.x)classBoo(object):def __init__(self, x):

self.x=xdef __add__(self, other):return 'Boo:%s + %s' %(self.x, other.x)

a= Foo(123)

b= Boo(321)print a +bprint b + a

在普通的加法运算中,调用的是+号左边的__add__方法,调用谁谁就为self。所以左边是self,右边为other,所以结果如上。

而反射运行其实就是交换这两者,下面看例子:

classFoo(object):def __init__(self, x):

self.x=xdef __radd__(self, other):return 'Foo:%s + %s' %(self.x, other.x)classBoo(object):def __init__(self, x):

self.x=xdef __radd__(self, other):return 'Boo:%s + %s' %(self.x, other.x)

a= Foo(123)

b= Boo(321)print a +bprint b + a

首先,不同的地方是这里调用的+后右边的__radd__方法。然后本来是左边的为self的,现在变成了右边的为self。

总结起来就是:普通的运算调用的是运算符左边的方法,而反射运算符调用的是右边的方法,调用的是谁的方法,谁就为self。

这里有几点要注意的地方:

1.不支持同一个类的实例进行反射运算:

classFoo(object):def __init__(self, x):

self.x=xdef __radd__(self, other):return 'Foo:%s + %s' %(self.x, other.x)

a= Foo(123)

b= Foo(321)print a +bprint b + a

2.当一个类实现了__add__的时候,将会掩盖__radd__方法,也就是__add__的优先度更高:

classFoo(object):def __init__(self, x):

self.x=xdef __radd__(self, other):return 'Foo:%s + %s' %(self.x, other.x)classBoo(object):def __init__(self, x):

self.x=xdef __add__(self, other):return 'Boo add:%s + %s' %(self.x, other.x)def __radd__(self, other):return 'Boo radd:%s + %s' %(self.x, other.x)

a= Foo(123)

b= Boo(321)print a +bprint b + a

其逻辑如下:

首先a + b,python看到了 a 中没有 __add__方法(忽略了__radd__),就去 b 中找__radd__(而不是__add__),因为在右边找的时候,就意味要使用反射运算了。所以最后得到了这个结果。

然后是b + a,python看到了 b 中有 __add__方法,就直接调用了它,不管 a 的内部是如何的。

基本反射运算就是这么一回事,下面是一些总结:

__radd__(self, other)

反射加法

__rsub__(self, other)

反射减法的

__rmul__(self, other)

反射除法

__rfloordiv__(self, other)

反射地板除,使用//运算符的

__rdiv__(self, other)

反射除法,使用/运算符的.

__rtruediv__(self, other)

反射真除.注意只有from __future__ import division 的时候它才有效

__rmod__(self, other)

反射取模运算,使用%运算符.

__rdivmod__(self, other)

长除法,使用divmod()内置函数,当divmod(other,self)时被调用.

__rpow__

反射乘方,使用**运算符的

__rlshift__(self, other)

反射左移,使用<

__rrshift__(self, other)

反射右移,使用>>操作符.

__rand__(self, other)

反射位与,使用&操作符.

__ror__(self, other)

反射位或,使用|操作符.

__rxor__(self, other)

反射异或,使用^操作符.

增量运算

所谓的增量运算,其实就是 x += 1 这样的形式,下面是几个例子:

classFoo(object):def __init__(self, x):

self.x=xdef __iadd__(self, other):return 'Foo iadd: %s + %s' %(self.x, other)

a= Foo(123)

a+= 1

print a

但是,如果两个对象的实现了__iadd__,情况就会大为不同:

classFoo(object):def __init__(self, x):

self.x=xdef __iadd__(self, other):return 'Foo iadd: %s + %s' %(self.x, other.x)classBoo(object):def __init__(self, x):

self.x=xdef __iadd__(self, other):return 'Boo iadd: %s + %s' %(self.x, other.x)

a= Foo(123)

b= Boo(321)

a+=bprint a

看似很正常,然而代码如下时:

a = Foo(123)

b= Boo(321)

a+=bprinta

b+=aprint b

报错显示:str没有x这个属性,但是按照代码来看,两个对象都有x属性呀。

在b += a 这行有错,也就是说self为 b,other为 a。后来试验了一番,发现将:

return 'Boo iadd: %s + %s' % (self.x, other.x)

改为:

return 'Boo iadd: %s + %s' % (self.x, other)

代码就不会报错了,但是输出几个如下:

很奇怪,other变成了a中__iadd__的返回值了,也就是说当a调用了__iadd__方法之后,在将其用在其他的增量运算时,other不在代表a对象本身,而是其__iadd__的返回值。

当我们回归其本质:x += 1 ==> x = x + 1 可以看出,x 其实进行了重新赋值,重新赋值成了 __iadd__ 的返回值。而我们代码示例中,这个方法的返回值是一个字符串。在一开始时,x是我们类的实例。但是在进行了增量运算后,x 变成了魔法方法的返回值,也就是字符串了,所以才会出现以上的报错。

所以我们在使用的时候要注意 x 身份的改变,不然会有许多意想不到的麻烦。

关于增量方法的总结:

__iadd__(self, other)

加法赋值

__isub__(self, other)

减法赋值.

__imul__(self, other)

乘法赋值

__ifloordiv__(self, other)

整除赋值,地板除,相当于 //= 运算符.

__idiv__(self, other)

除法赋值,相当于 /= 运算符.

__itruediv__(self, other)

真除赋值,注意只有你 whenfrom __future__ import divisionis,才有效.

__imod_(self, other)

模赋值,相当于 %= 运算符.

__ipow__

乘方赋值,相当于 **= 运算符.

__ilshift__(self, other)

左移赋值,相当于 <<= 运算符.

__irshift__(self, other)

左移赋值,相当于 >>= 运算符.

__iand__(self, other)

与赋值,相当于 &= 运算符.

__ior__(self, other)

或赋值,相当于 |= 运算符.

__ixor__(self, other)

异或运算符,相当于 ^= 运算符.

欢迎大家交流。

参考资料:戳这里

最后

以上就是高高纸飞机为你收集整理的python 魔法方法加减乘除_python魔法方法-反射运算和增量运算的全部内容,希望文章能够帮你解决python 魔法方法加减乘除_python魔法方法-反射运算和增量运算所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部