构造和析构
1)魔法方法总被双下划线包围
2)魔力体现在方法在适当时机调用
_ _init_ _(self[,...])
该方法为构造方法,在类实例化为对象时首先调用,返回值一定是None,只在需要初始化时才重写
_ _new_ _(cls[,...])
_ _new_ _()才是类实例化时调用的第一个方法,它的第一个参数与众不同,不是self,而是这个类(cls),而其他参数会直接传递给_ _init_ _()方法
_ _new_ _()需要返回一个实例对象,通常是这个类实例化后的对象,也可返回其他对象
_ _new_ _()很少重写,一般只要当继承一个不可变的类型时,才需要重写
class CapStr(str):
def _ _new_ _(cls,string):
string = string.upper()
return str._ _new_ _(cls,string) #只重写关注的部分内容
>>>a = CapStr('haha')
>>>a
'HAHA'
_ _del_ _(self)
Python提供了一个析构器:_ _del_ _()方法,当对象被销毁时,该方法被调用,,即当垃圾回收机制回收该对象时调用,而不是del x(并不会自动调用_ _del_ _()方法)
>>>class C:
def_ _del_ _(self):
print("del is doing")
>>>c1 = C()
>>>c2 = c1
>>>del c1
>>>del c2
del is doing
算术运算
工厂函数
将int(),float(),str(),list(),tuple()这些BIF转化为工厂函数(不再是普通的BIF)
>>>type(int)
type类型,即类对象,所谓的工厂函数即类对象,当调用这些方法时,实际是创建一个相应的实例对象
>>>a = int('123')
>>>b = int('345')
>>>a + b
468
可见对象可以进行算术计算
算术操作符
算术运算相关的魔法方法,如
>>>class New_int(int): #(int)代表继承???
def _ _add_ _(self,other):
return int._ _sub_ _(self,other) #Python默认的魔法方法
def _ _sub_ _(self,other):
return int._ _add_ _(self,other) #Python默认的魔法方法
>>>b = New_int(5)
>>>a + b #涉及加法操作,自动调用魔法方法_ _add_ _()
-2
>>>a - b
8
>>>class Try_int(int):
def _ _add_ _(self,other):
return self + other
def _ _sub(self,other):
return self - other
>>>a = Try_int(1)
>>>b = Try_int(3)
>>>a + b
#error,陷入无限递归,因为涉及加法操作,自动调用魔法方法_ _add_ _(),返回值仍然是对象相加,再次自动调用魔法方法_ _add_ _(),进入死循环,可改写为
>>>class Try_int(int):
def _ _add_ _(self,other):
return int(self) + int(other)
def _ _sub(self,other):
return int(self) - int(other)
>>>a = Try_int(1)
>>>b = Try_int(3)
>>>a + b4
反运算
反运算相当于算术运算增加了"r",如add变为radd
>>>class Nint(int):
def _ _radd_ _(self,other)
return int._ _sub_ _(other,self) #参数位置调换
>>>a = Nint(5)
>>>b= Nint(3)
>>>a + b
8 #a对象(主动)默认有_ _add_ _()方法,所以b的_ _radd_ _()不执行
>>>1 + b
-2 #_ _add_ _()方法表示对象相加,1没有,则b的_ _add_ _()不执行
注意参数顺序的变化,此时self为b,other为1(1-3=-2)
增量赋值运算
>>>a = a + b
>>>a += b
一元操作符
_ _neg_ _()(表示正号行为),_ _pos_ _()(表示负号行为),_ _abs_ _()(表示当abs()调用时行为,取绝对值),_ _invert_ _()(按位取反行为)
简单定制
要求:
定制一个计时器的类
start和stop方法代表启动计时和停止计时
假设计时器对象t1,print(t1)和直接调用t1均显示结果
当计时器未启动或已经停止计时,调用stop方法会给予提示
两个计时器对象可相加
只使用提供的有限资源
总结:对象进行相关算术运算,自动调用魔法方法
_ _str_ _()和_ _repr_ _()魔法方法
>>>class A:
def _ _str_ _(self):
return "haha"
>>>a = A()
>>>print(a)
haha
>>>class B:
def _ _repr_ _(self):
return "hehe"
>>>b = B()
>>>b
hehe
localtime()返回一个时间元组的结构
import time as t
class MyTimer:
def start(self):
self.start = t.localtime()
print('start')
def stop(self):
self.stop = t.localtime()
self._calc() #内部方法,计算时间
print('stop')
def _ calc(self):
self.lasted = []
self.prompt ='total'
for index in range(6):
self.lasted.append(self.stop[index] - self.start[index])
self.prompt += str(self.lasted[index])
print(self.prompt)
def _ _str_ _(self):
return self.prompt
_ _repr_ _= _ _str_ _
#所有属于实例对象的变量最好在_ _init_ _()中先定义
def _ _init_ _(self):
self.prompt = 'need to be activated'
self.lasted = []
self.start = 0 #error,因为start方法的存在,属性覆盖方法
self.stop = 0
修改为
def _ _init_ _(self):
self.prompt = 'need to be activated'
self.lasted = []
self.begin = 0
self.end = 0
添加列表存放单位
def _ _init_ _(self):
self.unit = ['year','month','day','hour','minute','second'] #修改处
self.prompt = 'need to be activated'
self.lasted = []
self.begin = 0
self.end = 0
def _ calc(self):
self.lasted = []
self.prompt ='total'
for index in range(6):
self.lasted.append(self.stop[index] - self.start[index])
if self.lasted[index]:
self.prompt += (str(self.lasted[index]) + self.unit[index])
#初始化变量
self.begin = 0
self.end = 0
#计时器对象相加,返回时间和
def _ _add_ _(self,other)
prompt = "total"
for index in range(6):
result.append(self.lasted[index] + other.lasted[index])
if result[index]:
prompt += (str(result.lasted[index]) + self.unit[index])
return prompt