重载是面向对象的一个重要概念,在很多程序实现中都会用到。最常见的是运算重载,比如+、-、x、÷等。python可以重载的方法一共有118个,有些是常用的,有些是不常用的。本文总结了所有的重载方法并提供实现实例以及说明供大家参考。为了便于阅读,本文分为常用的重载方法、其余重载方法以及重载方法列表。

一、重载的概念

重载的概念及时重新编写python类中的方法,以实现特定的算法或者处理。比如自定义的类的相加。

二、常用的重载方法

1. 运算符号

python支持运算符如下:

运算类型 对象在左侧 对象在右侧 复合赋值
加法 __add__ __radd__ __iadd__
减法 __sub__ __rsub__ __isub__
乘法 __mul__ __rmul__ __imul__
除法 __truediv__ __rdiv__ __idiv__
求余 __mod__ __rmod__ __imod_
运算符+
代码如下:

```python
class op(object):
    def __init__(self,x=0,y=0):
        self.x = x
        self.y = y

    def __str__(self): #重载__str__
        return ("x={} y={}".format(self.x,self.y))

    def __add__(self,other):
        print("对象在左侧")
        return op(self.x+other.x,self.y+other.y)

    def __radd__(self,other):
        print("对象在右侧")
        return op(self.x + other[0], self.y + other[1])

    def __iadd__(self, other):
        print("+=运算")
        self.x += other.x
        self.y += other.y
        return self

a = op(10,2)
c = a + op(5,9)
print("左侧:",c) #10+5,2+9
c = [1,2]+a
print("右侧",c) #1+10,2+2
c += a 
print("+=",c) #11+10,4+2

结果如下:

对象在左侧
左侧: x=15 y=11
对象在右侧
右侧 x=11 y=4
+=运算
+= x=21 y=6

不仅可以编写里2个对象的相加,也可以通过重载编写对象与数组,数字等方式的相加。不过这一点python不如C++方便。比如上面的例子中定义了对象+对象,就不能定义对象+数组。在右侧相加的方法中,定义了数组+对象。二者之间是有区别的。
其他的-、x、÷运算可以参考运算符+。
此外还有其他的运算,比如divmod(a//b,a%b)。
下面的示例是divmod

import math

class v(object):
    def __init__(self,x=0.,y=0.):
        self.x = x
        self.y = y

        self.xmod = None
        self.ymod = None
    def __divmod__(self, other):
        return divmod(self.x,other.x),divmod(self.y,other.y)

x,y = divmod(v(100,200),v(20,30))
print(x,y)

结果:

(5, 0) (6, 20)

2. 位运算

python对象的位运算有:&、|、^、~、>>、<<,含义如下:

位运算 含义 示例 方法
& 按位与 4&2=0 __and__
| 按位或 4&2=6 __or__
^ 按位异或 3^2=1 __xor__
~ 按位取反 ~2=-3 __invert__
>> 右移 8>>1=4 __rshift__
<< 左移 8<<1=16 __lshift__

位运算符也有赋值位运算,|=、&=、^=、>>=、<<=

#coding:utf8

class v(object):
    def __init__(self,x=0,y=0):
        self.x = x
        self.y = y

    def __or__(self, other):
        return v(self.x|other.x,self.y|other.y)

    def __and__(self,other):
        return v(self.x&other.x,self.y&other.y)

    def __ior__(self, other):
        print("ior",end=" ")
        self.x |= other.x
        self.y |= other.y
        return self

    def __iand__(self, other):
        print("iand",end=" ")
        self.x &= other.x
        self.y &= other.y
        return self

    def __xor__(self, other):
        return v(self.x^other.x,self.y^other.y)

    def __ixor__(self, other):
        print("ixor",end=" ")
        self.x ^= other.x
        self.y ^= other.y
        return self

    def __invert__(self):
        self.x = ~self.x
        self.y = ~self.y
        return self

    def __lshift__(self, other):
        return v(self.x<<other.x,self.y<<other.y)

    def __ilshift__(self, other):
        print("ilshift",end=" ")
        self.x = self.x << other.x
        self.y = self.y << other.y
        return self

    def __rshift__(self, other):
        return v(self.x>>other.x,self.y>>other.y)

    def __irshift__(self, other):
        print("irshift",end=" ")
        self.x = self.x >> other.x
        self.y = self.y >> other.y
        return self

    def __str__(self):
        return "x={},y={}".format(self.x,self.y)

a=v(3,6)
b=v(2,8)
c=v(3,6)
print("(",a,") | (",b,")=",a|b)
print("(",a,") & (",b,")=",a&b)
print("(",a,") ^ (",b,")=",a^b)
print("(",a,") >> (",b,")=",a>>b)
print("(",a,") << (",b,")=",a<<b)
print("~(",c,") =",~a) #~a 会改变a的值,用c暂存
a=v(3,6)
a ^= b
print(a)
a=v(3,6)
a &= b
print(a)
a=v(3,6)
a|=b
print(a)
a=v(3,6)
a>>=b
print(a)
a=v(3,6)
a<<=b
print(a) 

结果:

( x=3,y=6 ) | ( x=2,y=8 )= x=3,y=14
( x=3,y=6 ) & ( x=2,y=8 )= x=2,y=0
( x=3,y=6 ) ^ ( x=2,y=8 )= x=1,y=14
( x=3,y=6 ) >> ( x=2,y=8 )= x=0,y=0
( x=3,y=6 ) << ( x=2,y=8 )= x=12,y=1536
~( x=3,y=6 ) = x=-4,y=-7
ixor x=1,y=14
iand x=2,y=0
ior x=3,y=14
irshift x=0,y=0
ilshift x=12,y=1536

同样的有rand、ror、rshift、rlshift、rrshift等右侧位运算符。跟第一节的定义一样的,可以参考。

3.重要方法

比较常用的重要方法有:__init__。

__init__ 构造函数

用来初始化类。与C++不同的是python只能有一个初始化构造函数。可以写多个,但是只有最后一个有效。
如果需要多个不同的构造函数,可以把所有的成员变量作为构造函数的初始化参数,并且设置初始值。在创建对象的时候,通过参数=数值的形式实现不同的构造函数。示例如下:

#coding:utf8

class v(object):
    def __init__(self,x=0,y=None):
        self.x = x
        self.y = y

    def __str__(self):
        if self.y:
            return "x={0},y={1}".format(self.x,self.y)
        else:
            return "x={0},y={1}".format(self.x, "None")

a = v(x=1) #只有成员x
b = v(y=[10,11,12]) #只有成员y
c = v(x=100,y=[1,2,3]) #x和y都有
n = v() #使用默认值

print(a,b,c,n)

结果如下:

x=1,y=None
x=0,y=[10, 11, 12]
x=100,y=[1, 2, 3]
x=0,y=None

__str__和__repr__

见上例。二者实现的功能类似。如果是打印对象数组,系统调用的是__repr__

4.关系运算

关系运算是比较2个对象,包括:

关系运算 含义
__lt__ X<Y
__gt__ X>Y
__le__ X<=Y
__ge__ X>=Y
__eq__ X==Y
__ne__ X!=Y
__cmp__ 比较X和Y,用于sorted,返回值是-1,1,0

示例如下:

class v(object):
    def __init__(self,x=0):
        self.x = x

    def __lt__(self,other):
        return self.x < other.x

    def __gt__(self, other):
        return self.x > other.x

    def __le__(self, other):
        return self.x <= other.x

    def __ge__(self, other):
        return self.x >= other.x

    def __ne__(self, other):
        return self.x != other.x

    def __eq__(self, other):
        return self.x == other.x


print(v(1)<v(2))
print(v(1)>v(2))
print(v(2)<=v(2))
print(v(3)>=v(2))
print(v(1)!=v(2))
print(v(3)==v(3))

结果:

True
False
True
True
True
True

5. 转换

转为int,float等。具体转换功能如下:

转换类型 方法
bool __bool__
bytes __bytes__
complex __complex__
float __float__
int __int__

示例如下:

#coding:utf8

class v(object):
    def __init__(self,x=0,y=0):
        self.x = x
        self.y = y

    def __int__(self):
        return int(self.x)

    def __float__(self):
        return float(self.x)

    def __bool__(self):
        return bool(self.x)

    def __bytes__(self):
        return bytes(self.x)

    def __complex__(self):
        return complex(self.x)

    def __str__(self):
        return "x={},y={}".format(self.x,self.y)

a=v(3,6)
print("int:",int(a))
print("float:",float(a))
print("bool:",bool(a))
print("bytes:",bytes(a))
print("complex:",complex(a))

结果:

int: 3
float: 3.0
bool: True
bytes: b'\x00\x00\x00'
complex: (3+0j)

需要注意的是返回的一定是数字类型,不能是对象。

6. 数学运算

数学运算包括round、ceil、floor等。具体如下:

数学运算 方法 说明
abs __abs__ 绝对值
ceil __ceil__ 向上取整
floor __floor__ 向下取整
pow __pow__ 幂次运算
round __round__ 截取
trunc __trunc__ 截断为整数
matmul __matmul__ 矩阵乘积。与numpy的功能一致
pos __pos__ 返回数值本身
neg __neg__ 返回相反数

示例如下:

#coding:utf8
import math

class v(object):
    def __init__(self,x=0.,y=0.):
        self.x = x
        self.y = y
    def __abs__(self):
        return v(abs(self.x),abs(self.y))

    def __ceil__(self):
        return v(math.ceil(self.x),math.ceil(self.y))

    def __floor__(self):
        return v(math.floor(self.x),math.floor(self.y))

    def __pow__(self, power, modulo=None):
        return v(pow(self.x,power,modulo), pow(self.y,power,modulo))

    def __round__(self,n=None):
        return v(round(self.x,n),round(self.y,n))

    def __trunc__(self):
        return v(math.trunc(self.x),math.trunc(self.y))

    def __str__(self):
        return "x={},y={}".format(self.x,self.y)

a=v(3.14,6.28)
print(abs(v(-1,2)))
print(math.ceil(a))
print(math.floor(a))
print(pow(a,2))
print(round(a,1))
print(math.trunc(a))

结果:

x=1,y=2
x=4,y=7
x=3,y=6
x=9.8596,y=39.4384
x=3.1,y=6.3
x=3,y=6

7. 遍历与查找

遍历是遍历类中的数组、字典等成员。方法如下:

方法 说明 使用
__getitem__ 获取元素 x[key]
__setitem__ 设置指定位置元素 x[key]=value
__delitem__ 删除指定位置元素 del x[key]
__missing__ 判断是否存在索引key 由__getitem__被动调用
__contains__ 判断item是否在成员中 x.__contains__(item)
#coding:utf8

class v(object):
    def __init__(self,x=None):
        self.x = x

    def __getitem__(self, item):
        return self.x[item]

    def __setitem__(self, key, value):
        self.x[key]=value
    def __delitem__(self, key):
        self.x.pop(key)

    def __str__(self):
        return "x={}".format(self.x)
a=v([1,2,3,10])
print(a[3])
a[3]=100
print(a[3])
del a[2]
print(a)

结果:

10
100
x=[1, 2, 100]

8. 属性

属性包括len、sizeof等。具体如下:

方法 说明 使用
__len__ 对象大小 len(x)
__sizeof__ 返回对象所占的内存字节大小 x.__sizeof__()

9. 其他算法

方法 说明 使用
__hash__ 返回hash值 hash(x)

来源:风华明远

物联沃分享整理
物联沃-IOTWORD物联网 » python 重载

发表回复