python魔法方法-反射运算和增量运算
反射运算
什么是反射运算符,其实就是反转了两个对象,下面先看一个普通运行符的实现:
class Foo(object):
def __init__(self, x):
self.x = x def __add__(self, other):
return 'Foo:%s + %s' % (self.x, other.x) class Boo(object):
def __init__(self, x):
self.x = x def __add__(self, other):
return 'Boo:%s + %s' % (self.x, other.x) a = Foo(123)
b = Boo(321)
print a + b
print b + a
在普通的加法运算中,调用的是+号左边的__add__方法,调用谁谁就为self。所以左边是self,右边为other,所以结果如上。
而反射运行其实就是交换这两者,下面看例子:
class Foo(object):
def __init__(self, x):
self.x = x def __radd__(self, other):
return 'Foo:%s + %s' % (self.x, other.x) class Boo(object):
def __init__(self, x):
self.x = x def __radd__(self, other):
return 'Boo:%s + %s' % (self.x, other.x) a = Foo(123)
b = Boo(321)
print a + b
print b + a
首先,不同的地方是这里调用的+后右边的__radd__方法。然后本来是左边的为self的,现在变成了右边的为self。
总结起来就是:普通的运算调用的是运算符左边的方法,而反射运算符调用的是右边的方法,调用的是谁的方法,谁就为self。
这里有几点要注意的地方:
1.不支持同一个类的实例进行反射运算:
class Foo(object):
def __init__(self, x):
self.x = x def __radd__(self, other):
return 'Foo:%s + %s' % (self.x, other.x) a = Foo(123)
b = Foo(321)
print a + b
print b + a
2.当一个类实现了__add__的时候,将会掩盖__radd__方法,也就是__add__的优先度更高:
class Foo(object):
def __init__(self, x):
self.x = x def __radd__(self, other):
return 'Foo:%s + %s' % (self.x, other.x) class Boo(object):
def __init__(self, x):
self.x = x def __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 + b
print 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 这样的形式,下面是几个例子:
class Foo(object):
def __init__(self, x):
self.x = x def __iadd__(self, other):
return 'Foo iadd: %s + %s' % (self.x, other) a = Foo(123)
a += 1
print a
但是,如果两个对象的实现了__iadd__,情况就会大为不同:
class Foo(object):
def __init__(self, x):
self.x = x def __iadd__(self, other):
return 'Foo iadd: %s + %s' % (self.x, other.x) class Boo(object):
def __init__(self, x):
self.x = x def __iadd__(self, other):
return 'Boo iadd: %s + %s' % (self.x, other.x) a = Foo(123)
b = Boo(321)
a += b
print a
看似很正常,然而代码如下时:
a = Foo(123)
b = Boo(321)
a += b
print a
b += a
print 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魔法方法大全
1.python魔法方法详解: python魔法方法是可以修改重载的,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而 ...
- with上下文管理 python魔法方法
with语法在Python里很常见, 主要的利好是使用代码更简洁. 常见的使用场景有: 1. 资源对象的获取与释放. 使用with可以简化try...finally ... 2. 在不修改函数代码的前 ...
- python 魔法方法诠释
什么是Python魔法方法 什么是魔法方法呢?它们在面向对象的Python的处处皆是.它们是一些可以让你对类添加"魔法"的特殊方法. 它们经常是两个下划线包围来命名的(比如 ini ...
- Python魔法方法总结及注意事项
1.何为魔法方法: Python中,一定要区分开函数和方法的含义: 1.函数:类外部定义的,跟类没有直接关系的:形式: def func(*argv): 2.方法:class内部定义的函数(对象的方法 ...
- python 魔法方法补充(__setattr__,__getattr__,__getattribute__)
python 魔法方法补充 1 getattribute (print(ob.name) -- obj.func())当访问对象的属性或者是方法的时候触发 class F(object): def _ ...
- 1. Python 魔法方法
Python 魔法方法 基础: 如果你想... 所以,你写... Python调用... 初始化一个实例 x = MyClass() x.__init__() 作为一个字符串的"官方&quo ...
- python魔法方法:__getattr__,__setattr__,__getattribute__
python魔法方法:__getattr__,__setattr__,__getattribute__ 难得有时间看看书....静下心来好好的看了看Python..其实他真的没有自己最开始想的那么简单 ...
- python魔法方法-单目运算及一般算数运算
在比较的魔法方法中,我们讨论了魔法方法其实就是重载了操作符,例如>.<.==等.而这里,我们继续讨论有关于数值的魔法方法. 1.单目运算符或单目运算函数 __pos__(self) 实现一 ...
- python 魔法方法
I am not a creator, I just a porter. Note: Everything is object in python. 对于Python来说一切都是对象,也就是函数的参数 ...
随机推荐
- 使用密钥认证机制远程登录Linux
密钥认证机制 创建存放key的文件 1)创建目录 /root/.ssh 并设置权限 [root@localhost ~]# mkdir /root/.ssh mkdir 命令用来创建目录,以后会详细介 ...
- java中printf()方法简单用法
%n 换行 相当于 \n %c 单个字符 %d 十进制整数 %u 无符号十进制数 %f 十进制浮点数 %o 八进制数 %x 十六进制数 %s 字符串 %% 输出百分号 > 在printf()方法 ...
- 利用autocomplete.js实现仿百度搜索效果(ajax动态获取后端[C#]数据)
实现功能描述: 1.实现搜索框的智能提示 2.第二次浏览器缓存结果 3.实现仿百度搜索 <!DOCTYPE html> <html xmlns="http://www.w3 ...
- 配置samba文件服务器
1.打开"终端窗口",输入"sudo apt-get update"-->回车-->"输入当前登录用户的管理员密码"--> ...
- opencv 图像深度(depth)
原文地址:http://blog.csdn.net/dingfc/article/details/7457984 图像深度是指存储每个像素所用的位数,也用于量度图像的色彩分辨率.图像深度确定彩色图像的 ...
- centos6.5环境通达OA数据库mysql5.0.67升级至mysql5.5.48方案
centos6.5环境通达OA数据库mysql5.0.67升级至mysql5.5.42方案 整体方案: 环境准备,在备用服务器安装mysql5.5数据库 1.停用生产环境的应用访问 直接修改web的访 ...
- lvs持久连接及防火墙标记实现多端口绑定服务
lvs持久连接及防火墙标记实现多端口绑定服务 LVS持久连接: PCC:将来自于同一个客户端发往VIP的所有请求统统定向至同一个RS: PPC:将来自于一个客户端发往某VIP的某端口的所有请求统统定向 ...
- Ex 6_5棋子放置问题_第八次作业
题目貌似有问题 (b) 子问题定义: 设maxValue[i][j]为棋盘的前i行中最后一行为i时第i行按照第j种放置方式放置时得到的最大覆盖值,comp[i][j]为第i种放置方式与第j种放置方式是 ...
- PHP常见错误提示含义解释
1.Notice: Undefined variable: 变量名 in 注:使用了一个没有被定义的变量 2.Parse error: syntax error, unexpected T_ELSE ...
- PyCharm Professional破解版和汉化下载地址-new
2018.1版本下载地址 2018.2.1版本下载地址 今天找了很久很多都不能用了,注意破解过程提到的小细节,如果破解完了点击没反应请检查"pycharm.exe.vmoptions&quo ...