Python:魔法方法
学习资料:
引入:魔法方法的几个特征:
- 两边总是有双下划綫,eg:init
- 这些方法总能在适当时候被调用
- 这些方法是面向对象的Python的重要部分
Part 01:构造和折构
__init__(self[,...])
类在实例化对象时会调用的方法。
class Rectangle:#定义一个矩形需要长和宽
def __init__(self,x,y):#实例化时用默认init,因其没有参数需要重写
self.x=x#左边为类实例化定义的对象,右边为传入的参数
self.y=y
#init方法返回值一定是none,不要试图return
def getPeri(self):
return (self.x+self.y)*2
def getarea(self):
return self.x*self.y
>>>rect=Rectangle(3,4)
>>>rect.getPeri()
14
>>>rect.getarea()
12
__new__(cls[,...])
实例化对象时第一个被调用的方法,与其他魔法方法不同,它的第一个参数是cls(class),其后的参数可以原封不动的传给init,new方法需要一个实例对象作为返回值,通常为class对象。平时极少重写__new__,除了当继承一个不可变类型又需要修改的时候。
例:
class CapStr(str):
def __new__(cls,string):
string=string.upper()#str不可修改所以必须在实例化之前就对其进行修改
return str.__new__(cls,string)
>>>a=CapStr("i love mom")
>>>a
"I LOVE MOM"
#由于str不可改变,所以就不能在init方法内进行修改,init本身就是一个不可改变的对象。
__del__(self)
当对象将要被销毁时自动调用。注意:写del x
不相当于自动调用del,del是当没有任何变量引用这个对象(当所有引用都被del后,才会启用垃圾回收机制)时,垃圾回收机制会自动把它销毁,此时自动调用。
Part 02:算术运算
Python可以自定义对象的数值处理,通过对魔法方法的重写,可以自定义任何对象间的算数运算:
(来自B站小甲鱼)
- 真除法:结果得到小数
- 整数除法:结果把小数去掉
- divmod(a,b):相当于a/b的余数
- 位:CPU认为的最小单位,1字节=8位
例:
class Cul_int(int):
def __add__(self,other):
return int(self)+int(other)
def __sub__(self,other):
return int(self)-int(other)
>>>a=Cul_int(3)
>>>b=Cul_int(5)
>>>a+b
8
#self和other不加int()会进入无线递归.因为+时自动调用add,返回self+other,然后self+other又return a+b,进入无限循环。
自定义运算
重写实例:
class int(int):#新类把原来的int覆盖
def __add__(self,other):
return int.__sub__(self,other)#加法操作时输出的是减法的结果
>>>a=int(5)
>>>b=int(3)
>>>a+b
2
反运算
反运算符即上述运算符加上’r’,eg:__radd__()
.重写反运算时对于注重操作顺序的运算符注意self和other的顺序。
增量赋值运算
eg:a=a+b即a+=b
一元操作符
abs()为取绝对值
Part 03:简单定制
定制内容:
一个计时器的类,用start和stop启动和停止计时;
假设计时器对象为t1,print(t1)和直接调用它均显示结果;
当计时器未启动或已停止计时时,调用stop给予提示;
两计时器对象可以相加:t1+t2;
所需资源:
用localtime方法获取时间(参考:https://fishc.com.cn/forum.php?mod=viewthread&tid=51326&extra=page%3D1%26filter%3Dtypeid%26typeid%3D403);
time.localtime返回stuct_time的时间格式;
表现类:str__和__repr
import time as t#使输入t.就能调用time模块中的方法
class Mytimer():
def __init__(self):
self.unit=['year','mon','day','hour','min','sec']
self.prompt='未开始计时'
self.last=[]
self.begin=0
self.end=0
def __str__(self):
return self.prompt
__repr__=__str__
def __add__(self,other)
prompt='共运行了'
result=[]
for index in range(6):
result.append(self.last[index]+other.last[index])
if result[index]:
prompt+=(str(result[index]+self.unit[index]))
return prompt
def start(self):
self.begin=t.localtime()
self.prompt='请先结束'
print('计时开始')#开始计时
def stop(self):
if not self.begin:
print('请先开始')
else:
self.end=t.localtime()
self._cul()
print('计时结束')#结束计时
def _cul(self):
self.last=[]
self.prompt='共运行了'
for index in range(6):
self.last.append(self.end[index]-self.begin[index])
if self.last[index]:
self.prompt+=str(self.end[index])
print(self.prompt)
self.begin=0
self.end=0
>>> t1=Mytime()
>>> t2=Mytime()
>>> t1
请先开始
>>> t1.start()
计时开始
>>> t1.stop()
共运行了4秒
>>> t2.start()
计时开始
>>> t2.stop()
共运行了6秒
>>> t1+t2
'共运行了10秒'
Part 04:属性访问及描述符