概述
python类的运算符重载意味着在类方法中拦截内置的操作,当类的实例出现在内置操作中,python自动调用你重载的方法。常见的运算符重载方法如下(运算符的重载都是在类中进行定义的):
__init__,__del__,__new__
方法:__init__ 重载了:构造函数 ;程序中的调用方式: X = Class(args)对象建立
方法:__del__ 重载了:析构函数 ;程序中的调用方式: del var 删除对象引用,当对象的引用变为0时会自动调用__del__方法。一般来说python的对象回收机制的析构函数很少使用(因为无法确定会何时调用__del__函数)
方法:__new__ 重载了:申请内存空间 ;程序中的调用方式: 在init前在内存中创建内存空间,是一个静态函数
__add__,__radd__,__iadd__
方法:__add__ 重载了:运算符+ ;程序中的调用方式:如果没有__iadd__ ,X+Y, X+=Y
方法:__iadd__ 重载了:实地加法 ;程序中的调用方式:X+=Y
方法:__radd__ 重载了:右侧加法;程序中的调用方式:Other+X,只有当+右侧对象是类实例,左侧对象不是类实例时,python才会调用__radd__,(__radd__一般用来支持可互换的运算符)
当不同类的实例混合出现在表达式时,python优先选择左侧的那个类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34class (object):
def __init__(self, value):
self.value = value
def __add__(self, other):
print('add', self.value, other)
return self.value + other
def __radd__(self, other):
print('radd', self.value, other)
return other + self.value
x = MyObject(88)
print(x+2) # x传入self中,2 传入other中
"""
输出结果:
add 88 2
90
"""
y = MyObject(99)
print(1+y) # y传入self中,other传入1 ,调用__radd__
"""
输出结果:
radd 99 1
100
"""
print(x + y) # x+y 调用__add__,__add__再调用__radd__
"""
输出结果:
add 88 <__main__.myobject object at>
radd 99 88
187
"""
上例中,如果不定义__radd__运行x+y会报错,如果不想报错,可以使用下面办法
1
2
3
4
5
6
7
8
9
10
11
12
13
14class (object):
def __init__(self, value):
self.value = value
def __add__(self, other):
if isinstance(other, MyObject):
other = other.value
return self.value + other
x = MyObject(88)
y = MyObject(99)
print(x + y) # x+y 直接调用__add__ 187
__or__,__ior__
方法:__or__ 重载了:运算符| ;程序中的调用方式:如果没有__ior__ ,X|Y, X|=Y
__repr__,__str__
方法:__repr__、__str__ 重载了:打印转换;程序中的调用方式:print(X),repr(X),str(X),返回字符串表达形式
打印会首先尝试__str__,交互模式下会首先尝试__repr__
__index__
方法:__index__ 重载了:整数值;程序中的调用方式:hex[X]、bin(X)、oct(X),返回一个整数值
__call__
方法:__call__ 重载了:函数调用;程序中的调用方式:X(*args , **kwargs)
__getattr__,__setattr__,__delattr__,__getattribute__,__get__,__set__
方法:__getattr__ 重载了:点号运算;程序中的调用方式:X.undefined。即当通过对未定义的属性名称和实例进行点好运算时,就会用属性名称作为字符串调用这个方法。如果python可以通过其继承树搜索流程找到这个属性,该方法不会被调用
方法:__setattr__ 重载了:属性赋值语句;程序中的调用方式:X.any = value,使用X.any = value相当于调用self.__setattr__('attr',value),因此在__setattr__ 中对任何self属性做赋值都会在调用__setattr__ ,导致无穷递归循环,如果要使用这个方法,要通过对属性字典做索引运算来进行赋值来避免无穷循环
方法:__delattr__ 重载了:属性删除;程序中的调用方式:del X.any
方法:__getattribute__ 重载了:属性获取;程序中的调用方式:X.any(getattr(X,attr)公共函数默认调用这个方法)
方法:__get__,__set__ 重载了:描述符属性;程序中的调用方式:X.attr,X.attr = value, del X.attr
1
2
3
4
5
6
7
8
9
10
11
12
13class (object):
def __setattr__(self, attr, value):
if attr == 'age':
self.__dict__[attr] = value # 不可以使用self.attr = value避免循环调用
else:
raise AttributeError(attr + ' not allowed')
X = MyObject()
X.age = 40
print(X.age) # 40
X.name = 'mel' # 出错 AttributeError: name not allowed
__getitem__,__setitem__,__delitem__
方法:__getitem__ 重载了:索引运算;程序中的调用方式:X[key],X[i:j],没有__iter__时的for循环和其他迭代器
方法:__setitem__ 重载了:索引赋值语句;程序中的调用方式:X[key]=value,X[i:j]=sequence
方法:__delitem__ 重载了:索引和切片删除;程序中的调用方式:del X[key],del X[i:j]
1
2
3
4
5
6class (Object):
def __getitem__(self,index):
pass
return something
def __setitem__(self,index,value)
pass # set something
__iter__,__next__
重载了:迭代环境;程序中的调用方式:I = iter(X),next(I),map(F,X)等其他迭代情况
python的所有迭代环境中都会优先尝试__iter__方法,没有__iter__才会尝试__getitem__方法
1
2
3
4
5
6
7class (object):
def __iter__(self):
pass
return self # return self只支持单一迭代器
def __next__(self)
if test :raise StopIteration # 如果超过边界则产生异常
return something
__len__,__bool__
方法:__len__ 重载了:长度;程序中的调用方式:len(X),如果没有__bool__的真值测试,则尝试通过__len__来获取真值信息
方法:__bool__ 重载了:布尔测试;程序中的调用方式:bool(X)
__lt__,__gt__,__le__,__ge__,__eq__,__ne__
重载了:特定的比较;程序中的调用方式:XY,X<=Y,X>=Y,X==Y,X!=Y返回布尔值
注意:__eq__,__ne__必须都定义
__contains__
重载了:成员关系测试;程序中调用方式:item in X(任何可迭代的)
1
2
3
4class MyObject(object):
def __contains__(self,x): # 用于判断元素是否在x是否在self中
pass
return 布尔值
__enter__,__exit__
重载了:环境管理器;程序中的调用方式:with obj as var:
最后
以上就是殷勤金毛为你收集整理的python运算符重载_python类运算符重载的全部内容,希望文章能够帮你解决python运算符重载_python类运算符重载所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复