最近开始学习了一下Python,发现其有些特性还是挺诱人的,比如运算符可以重载。对于我这样习惯用C++的老农来说,Java这样不能重载运算符的OOP语言实在是感觉存在有些遗憾。而能支持重载运算符可以使自定义的类看上去更加的内置化一样。

python的运算符重载的方法有些特殊,不像是C++中的用operator关键字来实现的,而是使用了一些提前内置好的函数名来表示,比如__and__就是用来对应and运算符的函数,而__del__则是del关键字对应的方法。这里把常用的重载函数的名称列一下,备忘。

@可重载的运算符
基本定制类运算符
obj.__init__(self[, arg1, ...]) 构造器(带一些可选的参数)
obj.__new__(self[, arg1, ...]) 构造器(带一些可选的参数);通常用在设置不变数据类型的子类
obj.__del__(self) 解构器
obj.__str__(self) 可打印的字符输出;内建str()及print 语句
obj.__repr__(self) 运行时的字符串输出;内建repr() ‘‘ 和 操作符
obj.__unicode__(self)b Unicode 字符串输出;内建unicode()
obj.__call__(self, *args) 表示可调用的实例
obj.__nonzero__(self) 为object 定义False 值;内建bool() (从2.2 版开始)
obj.__len__(self) “ ” 长度(可用于类);内建len()

对象值比较类运算符
obj.__cmp__(self, obj) 对象比较;内建cmp()
obj.__lt__(self, obj) and 小于/小于或等于;对应<及<=操作符
obj.__le__(self,obj)
obj.__gt__(self, obj) and 大于/大于或等于;对应>及>=操作符
obj.__ge__(self,obj)
obj.__eq__(self, obj) and 等于/不等于;对应==,!=及<>操作符
obj.__ne__(self,obj)
 
属性操作类运算符
obj.__getattr__(self, attr) 获取属性;内建getattr();仅当属性没有找到时调用
obj.__setattr__(self, attr, val) 设置属性
obj.__delattr__(self, attr) 删除属性
obj.__getattribute__(self, attr) 获取属性;内建getattr();总是被调用
obj.__get__(self, attr) (描述符)获取属性
obj.__set__(self, attr, val) (描述符)设置属性
obj.__delete__(self, attr) (描述符)删除属性
 
数值及二进制类运算符
obj.__add__(self, obj) 加;+操作符
obj.__sub__(self, obj) 减;-操作符
obj.__mul__(self, obj) 乘;*操作符
obj.__div__(self, obj) 除;/操作符
obj.__truediv__(self, obj) True 除;/操作符
obj.__floordiv__(self, obj) Floor 除;//操作符
obj.__mod__(self, obj) 取模/取余;%操作符
obj.__divmod__(self, obj) 除和取模;内建divmod()
obj.__pow__(self, obj[, mod]) 乘幂;内建pow();**操作符
obj.__lshift__(self, obj) 左移位;<<操作符
 
二进制类运算符
obj.__rshift__(self, obj) 右移;>>操作符
obj.__and__(self, obj) 按位与;&操作符
obj.__or__(self, obj) 按位或;|操作符
obj.__xor__(self, obj) 按位与或;^操作符
一元类运算符
obj.__neg__(self) 一元负
obj.__pos__(self) 一元正
obj.__abs__(self) 绝对值;内建abs()
obj.__invert__(self) 按位求反;~操作符
 
数值转换类运算符
obj.__complex__(self, com) 转为complex(复数);内建complex()
obj.__int__(self) 转为int;内建int()
obj.__long__(self) 转为long;内建long()
obj.__float__(self) 转为float;内建float()
 
其他类运算符
obj.__oct__(self) 八进制表示;内建oct()
obj.__hex__(self) 十六进制表示;内建hex()
obj.__coerce__(self, num) 压缩成同样的数值类型;内建coerce()
obj.__index__(self)g 在有必要时,压缩可选的数值类型为整型(比如:用于切片索引等等
 
序列类运算符
obj.__len__(self) 序列中项的数目
obj.__getitem__(self, ind) 得到单个序列元素
obj.__setitem__(self, ind,val) 设置单个序列元素
obj.__delitem__(self, ind) 删除单个序列元素
 
obj.__getslice__(self, ind1,ind2) 得到序列片断
obj.__setslice__(self, i1, i2,val) 设置序列片断
obj.__delslice__(self, ind1,ind2) 删除序列片断
obj.__contains__(self, val) f 测试序列成员;内建in 关键字
obj.__add__(self,obj) 串连;+操作符
obj.__mul__(self,obj) 重复;*操作符
obj.__iter__(self) 创建迭代类;内建iter()
 
映射类运算符
obj.__len__(self) mapping 中的项的数目
obj.__hash__(self) 散列(hash)函数值
obj.__getitem__(self,key) 得到给定键(key)的值
obj.__setitem__(self,key,val) 设置给定键(key)的值
obj.__delitem__(self,key) 删除给定键(key)的值
obj.__missing__(self,key) 给定键如果不存在字典中,则提供一个默认值

 

解决为了实际问题,也为了巩固一下学习的成果,我写了一个complex类来实现复变函数中常用的复数运算,虽然python自己带有complex类,但是对于复变函数的运算来说有些力不从心,所以这里列出一些简单的复数运算的方法。

 

import math

def trim(f):
    fl, cl = math.floor(f), math.ceil(f)
    
    if f-fl < 1e-7: return int(fl)
    if cl-f < 1e-7: return int(cl)
    return f
    
class Complex:
    def __init__(self, real=0.0, image=0.0):
        self.real = trim(real)
        self.image= trim(image)
    
    def __nonzero__(self):
        return 1 if self.real or self.image else 0
    
    def __abs__(self):      # abs(cmpl)
        return math.sqrt(self.real**2+self.image**2)
    
    def __invert__(self):     #~cmpl 共轭复数
        return Complex(self.real, -self.image)
    
    def __add__(self, comp):   #a+b
        if type(comp) is type(self):
            return Complex(self.real+comp.real,
                           self.image+comp.image)
        else:
            return Complex(self.real-comp, self.image)
        
    def __sub__(self, comp):    #a-b
        if type(comp) is type(self):
            return Complex(self.real-comp.real,
                           self.image-comp.image)
        else:
            return Complex(self.real-comp, self.image)
        
    def __mul__(self, comp):        #a*b
        if type(comp) is type(self):
            return Complex(self.real*comp.real-self.image*comp.image, 
                           self.real*comp.image+self.image*comp.real)
        else:
            return Complex(self.real*comp, self.image*comp)
        
    def __div__(self, comp):      #a/b
        if not comp:
            raise Exception('Divided by zero.')
        if type(comp) is type(self):
            a, b, c, d = self.real, self.image, comp.real, comp.image
            return Complex(float(a*c+b*d)/(c*c+d*d), float(b*c-a*d)/(c*c+d*d))
        else:
            return Complex(float(self.real)/comp, float(self.image)/comp)
    
    def __pow__(self, comp):      #a**b   复数的指数运算
        leng = self.__abs__()
        angl = self.arg()
        if type(comp) is type(self):
            nleng= leng**comp.real
            nangl= (angl*comp.real)%(math.pi*2)
            rr = Complex()
            rr.setMA(nleng, nangl)
            zs = self.log()*comp.image
            xc = Complex(zs.cos(), zs.sin())
            return rr*xc
        else:
            mod = leng**comp
            ang = (angl*comp)%(math.pi*2)
            return Complex(mod*math.cos(ang), mod*math.sin(ang))
    
    def __and__(self, comp):     # a and b    判断a、b都不是零
        return self.__nonzero__() and bool(comp) 
    
    def __or__(self, comp):    #a or b  判断a、b不都为零
        return self.__nonzero__() or bool(comp)     
    
    def __repr__(self):      #str(cmpl)
        sreal = str(self.real) if self.real != 0 else ''
        if int(self.image) == self.image and int(self.image) in (0,1,-1):
            simage= {0:'',1:'i',-1:'-i'}[int(self.image)]
        else:
            simage= "%si"%self.image 
        
        if sreal and self.image > 0:
            return sreal +'+'+ simage
        elif sreal or simage:
            return sreal + simage
        else:
            return '0'
            
    
    def setMA(self, m, a):
        self.real, self.image = m*math.cos(a), m*math.sin(a)
    
    def arg(self):     #获取辐角(没有想好用什么运算符表示,所以只用arg函数来实现了)
        return math.atan2(self.image, self.real)
    
    def log(self):        #复数的自然对数
        if not self.__nonzero__():
            raise Exception('Zero is not logarithm for any.')
        ang, mod = self.arg(), self.__abs__()
        return Complex(math.log(mod), ang)
    
    def exp(self):       #复数的指数
        rr = math.exp(self.real)
        return Complex(rr*math.cos(self.image), rr*math.sin(self.image))
    
    def sin(self):        #正弦
        return math.sin(self.real) * math.cosh(self.image) + \
                math.sinh(self.image) * math.cos(self.real)
    
    def cos(self):       #余弦
        return math.cos(self.real) * math.cosh(self.image) - \
                math.sin(self.real) * math.sinh(self.image)
    
#还有用其它的函数,这里就不列出了
#其实就是得来复变函数的运算规则实现的复数运算

再添加一段简单的测试代码

 

if __name__ == '__main__':
    a = Complex(0.7071067811865476, 0.7071067811865476)
    b = a.log()
    print "ln(%s)=%s, %s"%(a, b, b.exp())
    print a**2
    a, b, o = Complex(5,3), Complex(2,-1), Complex()
    print abs(a), abs(b)
    print a+b, a-b, a/b, ~a,(a and b), (a or b), a**b
    
#     a = complex(1,2)
#     print math.log(a)