设为首页 加入收藏

TOP

python魔法方法-反射运算和增量运算(一)
2017-09-30 16:46:50 】 浏览:6478
Tags: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) 

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

 

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Python array,list,dataframe索引.. 下一篇Python Django中QQ邮箱授权码问题

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目