1.__del__
# ### __del__魔术方法(析构方法) ''' 触发时机:当对象被内存回收的时候自动触发(1.页面执行完毕回收所有变量2.所有对象被del的时候) 功能:对象使用完毕后资源回收 参数:一个self接收对象 返回值:无 ''' class LangDog(): food = "吃肉" def __init__(self,name): self.name = name def __del__(self): print("析构方法被触发") #(1) 页面执行完毕回收所有变量 obj= LangDog("刀疤") print(obj.name) ''' 打印结果: 刀疤 析构方法被触发 ''' #(2)所有对象被del的时候 ''' 当一个值,没有任何变量指向或者说引用,这个值才会被真正的释放 ''' other_obj = obj print(other_obj is obj) #True del obj #如果只删除这一个的话,那么就不会执行del方法 del other_obj ''' 打印结果: True 析构方法被触发 ''' #模拟文件操作 ''' fp = open(文件,模式,编码) fp.read() fp.close() ''' import os class ReadFile(): def __new__(cls,filename): #创建的时候就进行判断文件存在或不存在 #判断文件是否存在 if os.parh.exists(filename): return object.__new__(cls) else: print("文件不存在") def __init__(self,filename): #初始化对象的时候就进行打开文件操作 self.fp = open(filename,'r',encoding='utf-8') def readcontent(self):#读文件内容方法 content = self.fp.read() return content def __del__(self): #资源回收的时候关闭文件 self.fp.close() obj = ReadFile("ceshi.txt") res = obj.readcontent() print(res)
2.__str__和__repr__
# __str__ 魔术方法 ''' 触发时机:使用print(对象)或者str(对象)的时候触发 功能:查看对象 参数:一个self接收当前对象 返回值:必须返回字符串类型 ''' class Cat(): gift = "传说中的小猫有九条命,喜欢卖萌和上树" def __init__(self,name): self.name = name def __str__(self): return self.cat_info() def cat_info(self): return "{}小猫有故事--{}".format(self.name,self.gift) tom = Cat("汤姆") #触发方式一。print打印该对象 print(tom) #触发方式二,str转换对象 res = str(tom) print(res) # __repr__ 魔术方法 ''' 触发时机:使用repr(对象)的时候触发 功能:查看对象,与魔术方法__str__相似 参数:一个self接收当前对象 返回值:必须返回值是字符串类型 ''' class Mouse(): gift = '打洞' def __init__(self,name): self.name = name def __repr__(self): return self.mouse_info() def mouse_info(self): return "{}老鼠天赋是{},龙生龙,凤生凤,老鼠的儿子会打洞".format(self.name,self.gift) #在系统底层,如果定义了repr,将会默认赋值给str方法 #__str__ = __repr__ #repr 强转obj对象时触发 obj = Mouse() res = repr(obj) print(res) #注意点 底层存在赋值调用给str的语法,所以能实现打印或者str强转对象的触发机制 print(obj) res = str(obj) print(rs) #也就是如果先用的repr方法,那么可以也用str转 #但是如果先用的str方法,那么就不能用repr方法转
3.__call__
# ### __call__ 魔术方法 ''' 触发时间:把对象当做函数调用的时候自动触发 功能:模拟函数化操作 参数:参数不固定,至少一个self参数 返回值:看需求 ''' #(1) 基本用法 class MyClass(): a = 1 def __call__(self): print("call魔术方法被触发") obj = MyClass() obj() #(2) 模拟洗衣服的过程 class Wash(): #用call魔术方法统一调用 当实例化对象后加()当成函数用时触发下面 def __call__(self,something): self.step1(something) self.step2() self.step3() def step1(self,something): print("脱衣服,洗{}".format(something)) def step2(self): print("放水里,扔点洗衣液,洗衣粉,蓝月亮") def step3(self): print("扭干净,穿上") obj = Wash() obj('裤衩') #(3)模拟内置方法 int 实现myint import math class MyInt(): def mycalc(self,num,sign = 1): #去掉左边多余的0 strvar = num.lstrip("0") if strvar == '': return 0 #计算最终结果 return eval(strvar) * sign def __call__(self,num): #判断是布尔类型 if isinstance(num,bool): if num == True: return 1 else: return 0 #判断是整型 elif isinstance(num,int): return num #判断是浮点型 elif isinstance(num,float): #方法一 ''' strvar = str(num) return strvar.split(".")[0] ''' #方法二 ''' if num >= 0: return math.floor(num) else: return math.ceil(num) ''' return math.floor(num) if num >= 0 else math.ceil(num) elif isinstance(num,str): #首字符是+或者-,后面的是纯数字字符串 if (num[0] == "+" or num[0] == '-') and num[1:].isdecimal(): if num[0] == "+": sign = 1 else: sign = -1 return self.mycalc(num[1:],sign) elif num.isdecimal(): return self.mycalc(num) else: retun "老铁,这个真不能转" myint = MyInt() print( myint(0) ) #=> 3 print( myint(3.13) ) #=> 3 print( myint("+00000000000000000001003") ,"<==1=>") print( myint("+abcd") ,"<===>") print( myint("-0000000000000000000.1003") ,"<==2=>") print( int("0000000000000000000003") ) print( int("+0000000000000000000003") ) # print( int("+-+-+-+-+-+-1233444") ) print( myint("+-+-+-+-+-+-1233444") )
4.__bool__,__add__,__len__
# ### __bool__ ''' 触发时机:使用bool(对象)的时候自动输出 功能:强转对象 参数:一个self接收当前对象 返回值:必须是布尔类型 ''' ''' #类似的还有如下等等(了解): __complex__(self) 被complex强转对象时调用 __int__(self) 被int强转对象时调用 __float__(self) 被float强转对象时调用 ''' class MyClass(): def __bool__(self): return True obj = MyClass() res = bool(obj) print(res) #True #__add__ 魔术方法(与之相关的__radd__反向加法) ''' 触发时机:使用对象进行运算相加的时候自动触发 功能:对象运算 参数:二个对象参数 返回值:运算后的值 ''' ''' 类似的还有如下等等(了解): __sub__(self, other) 定义减法的行为:- __mul__(self, other) 定义乘法的行为: __truediv__(self, other) 定义真除法的行为:/ ''' class MyAdd(): def __init__(self,num): self.num = num #对象在加号+左侧的时候,自动触发 def __add__(self,other): return self.num + other def _radd__(self,other): return self.num + other * 2 #情况一 a = MyAdd(7) #self 接收a other接收7 触发的是__add__方法 #情况二 #res = a + 7 #self 接收a other接收7 触发的是__radd__方法 #res = 7 + a #print(res) #情况三 ''' a + b 先触发 __add__,self 接收的是7,other接收的是b res = 7 + b 7 + b 再触发 __radd__,self接收的是b,other接收的是7 return 8 + 7*2 = 22 res = 22 ''' b = MyAdd(8) res = a + b print(res) #__len__ 魔术方法 ''' 触发时机:使用len(对象)的时候自动触发 功能:用于检测对象中或者类中成员的个数 参数:一个self接收当前对象 返回值:必须返回整型 ''' ''' 类似的还有如下等等(了解): __iter__(self) 定义迭代容器中的元素的行为 __reversed__(self) 定义当被 reversed() 调用时的行为 __contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为 ''' #计算一下类中所有自定成员的个数 class MyClass(): pty1 = 1 pty2 = 2 __pty3 = 3 def func1(): pass def func2(): pass def func3(): pass def func4(): pass def __len__(self): #print(MyClass.__dict__) #lst = [] #for i in MyClass.__dict__: #print(i) #if not(i.startswith("__") and i.endswith("__")): #lst.append(i) #print(lst) #简写 lst = [i for i in MyClass.__dict__ if not (i.startswith("__") and i.endswith("__"))] return len(lst) obj = MyClass() print(len(obj)) """ { '__module__': '__main__', 'pty1': 1, 'pty2': 2, '_MyClass__pty3': 3, 'func1': <function MyClass.func1 at 0x000001FFAF8C4840>, 'func2': <function MyClass.func2 at 0x000001FFAF8C48C8>, '_MyClass__func3': <function MyClass.__func3 at 0x000001FFAF8C4950>, 'func4': <function MyClass.func4 at 0x000001FFAF8C49D8>, '__len__': <function MyClass.__len__ at 0x000001FFAF8C4A60>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None } """
5.与类相关的魔术属性
# ### 与类相关的魔术属性 class Man(): pass class Woman(): pass class Children(Man,Woman): ''' 成员属性:eye 成员方法:skylight moonread __makebaby 完成的功能:描述小孩天生神力 ''' eye = "血轮眼" def skyligth(self): print("一下生,直接使用天照,让世界变得混乱") def moonread(self,func): print("一下生,使出了武功绝学,月读,世界都黑暗里~") print(func.__name__,type(func.__name__)) #earth_boom def __makebaby(self): print("这一手招数,只能我自己用") obj = Children() # __dict__ 获取对象或类的内部成员结构 print(obj.__dict__) print(Children.__dict__) ''' {} {'__module__': '__main__', '__doc__': ' 成员属性:eye 成员方法:skylight moonread __makebaby 完成的功能:描述小孩天生神力 ', 'eye': '血轮眼', 'skylight': <function Children.skylight at 0x0000000002985620>, 'moonread': <function Children.moonread at 0x00000000029856A8>, '_Children__makebaby': <function Children.__makebaby at 0x0000000002985730>} ''' # __name__ 获取类名函数名 def eatrh_boom(): print("使用一招地爆天星") obj.moonread(earth_boom) obj.moonread(Children) ''' 一下生,使出了武功绝学,月读,世界都黑暗里~ earth_boom <class 'str'> 一下生,使出了武功绝学,月读,世界都黑暗里~ Children <class 'str'> ''' # __class__ 获取当前对象所属的类 print(obj.__class) #__bases__获取一个类直接继承的所有父类 返回元组 print(Children.__bases__) # (<class '__main__.Man'>, <class '__main__.Woman'>)
总结:
今天主要讲了几类魔术方法以及与类相关的魔术属性 首先讲了__del__魔术方法,又称析构方法 触发时机,当对象被内存回收的时候自动触发 (1.页面执行完毕回收所有变量2.所有对象被del的时候) 参数:一个self接收对象 返回值:无 __str__和__repr__ __str__魔术方法触发时机使用print打印对象或者str对象的时候触发 参数:一个self接收当前对象 返回值:必须返回字符串类型 __repr__魔术方法 触发时机使用repr对象的时候触发 功能与str魔术方法相似 参数:一个self接收对象 返回值必须返回字符串类型 要注意的时候,在系统底层如果定义了repr,将会默认赋值给str方法 即 __str__ = __repr__ #也就是如果先用的repr方法,那么可以也用直接打印或者str转 但是如果先用的str方法,那么就不能用repr方法转 call魔术方法触发时机把对象当做函数调用的时候自动触发 功能模拟函数化操作 参数不固定至少一个self参数 返回值看需求 bool魔术方法 触发时机:使用bool(对象)的时候自动输出 功能:强转对象 参数:一个self接收当前对象 返回值:必须是布尔类型 add魔术方法 与之相反的__radd__反向加法 触发时机:使用对象进行运算相加的时候自动触发 功能:对象运算 参数:二个对象参数 返回值:运算后的值 #对象在加号+左侧的时候,自动触发add魔术方法 对象在右侧时,自动触发__radd__魔术方法 __len__ 魔术方法 触发时机:使用len(对象)的时候自动触发 功能:用于检测对象中或者类中成员的个数 参数:一个self接收当前对象 返回值:必须返回整型 与类相关的魔术属性 __name__ 获取类名函数名 __dict__ 获取对象或类的内部成员结构 __class__ 获取当前对象所属的类 __bases__获取一个类直接继承的所有父类 返回元组