一.魔术方法
(1)__del__ 魔术方法(析构方法)
- 触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
- 功能:对象使用完毕后资源回收
- 参数:一个self接受对象
- 返回值:无
示例
class LangDog():
food = "改吃蔬菜"
def __init__(self,name):
self.name = name
def __del__(self):
print("析构方法被触发")
<1>页面执行完毕回收所有变量
1 obj = LangDog("肉丝")
2 print(obj.name)#最后一行代码结束后,析构方法被触发
<2>所有对象被del的时候
1 obj = LangDog("肉丝")
2 other_obj = obj
3 print("<=====start=====>")
4 del obj
5 del other_obj #对象全部被删除后,析构方法被触发
6 print("<=====end=====>")
<3>模拟文件操作
import os
class ReadFile():
def __new__(cls,filename):
if os.path.exists(filename):
return object.__new__(cls)
else:
return print("该文件是不存在的")
def __init__(self,filename):
# 打开文件
self.fp = open(filename,mode="r+",encoding="utf-8")
def readcontent(self):
# 读取文件
return self.fp.read()
def __del__(self):
# 关闭文件
self.fp.close()
obj = ReadFile("属性_反射.md")
if obj is not None:
res = obj.readcontent()
print(res)
else:
print("没有该类文件")
# 三运运算符
# 真值 if 条件表达式 else 假值
print(obj.readcontent()) if obj is not None else print("没有该类文件")
二.__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,5000)
__repr__ = __str__
<1>方法一. print(对象)
tom = Cat("汤姆")
print(tom)#触发__str__返回字符串
<2>方法二. str(对象)
res = str(tom)#触发__str__返回字符串用res接收
print(res)#打印返回的字符串
<3>小扩展 让repr强转对象时,触发打印内容
tom = Cat("汤姆")
res = repr(tom)# 类中 添加__repr__ = __str__
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)
# 系统在底层,自动加了一句赋值操作
__str__ = __repr__
<1>方法一. print(对象)
jerry = Mouse("杰瑞")
print(jerry)
<2>方法二. str(对象)
jerry = Mouse("杰瑞")
res = repr(jerry)
print(res)
<3>因为系统底层赋值的原因,在打印对象或者强转对象为字符串的时候,仍然可以触发
jerry = Mouse("杰瑞")
res = str(jerry)
print(res)
三.__call__ 魔术方法
- 触发时机:把对象当作函数调用的时候自动触发
- 功能: 模拟函数化操作
- 参数: 参数不固定,至少一个self参数
- 返回值: 看需求
(1) 基本用法
class MyClass():
a = 1
def __call__(self):
print("call魔术方法被触发了")
obj = MyClass()
obj()
(2) 模拟洗衣服的过程
class Wash():
def __call__(self,something):
print("我现在要洗{}".format(something))
self.step1()
self.step2()
self.step3()
return "洗完了"
def step1(self):
print("加热水,家洗衣粉,加洗衣液,加洗涤剂")
def step2(self):
print("衣服泡进去搅乱 打散 搓一搓~ ")
def step3(self):
print("脱水,穿上")
<1>方法一
1 obj = Wash()
2 obj.step1()#加热水,家洗衣粉,加洗衣液,加洗涤剂
3 obj.step2()#衣服泡进去搅乱 打散 搓一搓~
4 obj.step3()#脱水,穿上
<2>方法二
1 obj = Wash()
2 res = obj("衣服")
3 print(res)'''我现在要洗衣服
4 加热水,家洗衣粉,加洗衣液,加洗涤剂
5 衣服泡进去搅乱 打散 搓一搓~
6 脱水,穿上
7 洗完了
8 '''
(3) 模拟内置int 实现相应的操作
import math
class MyInt():
def calc(self,num,sign=1):
# 去掉左边多余的0
strvar = num.lstrip("0")
# 为了防止都是0 ,如果去掉之后为空,返回0
if strvar == "":
return 0
# 正常情况下,执行存数字字符串变成数字 , 在乘上相应的符号,得出最后的结果
return eval(strvar) * sign
def __call__(self,num):
if isinstance(num , bool):
if num == True:
return 1
elif num == False:
return 0
elif isinstance(num,int):
return num
elif isinstance(num,float):
# 方法一
"""
strvar = str(num)
lst = strvar.split(".")
return eval(lst[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.calc(num[1:],sign)
elif num.isdecimal():
return self.calc(num)
else:
return "老铁,这个真转不了"
测试
myint = MyInt()
print(myint(True))
print(myint(100))
print(myint(3333.14))
print(myint("+000000000234"))
print(myint("3.143434"))
print(myint("000000000000000000000000000000000000000000123"))
四.__bool__ 魔术方法
- 触发时机:使用bool(对象)的时候自动触发
- 功能:强转对象
- 参数:一个self接受当前对象
- 返回值:必须是布尔类型
其他类似方法如下(了解)
- __complex__(self) 被complex强转对象时调用
- __int__(self) 被int强转对象时调用
- __float__(self) 被float强转对象时调用
- ...
示例
class MyClass():
def __bool__(self):
return False
obj = MyClass()
res = bool(obj)
print(res)
五.__add__ 魔术方法 (与之相关的__radd__ 反向加法)
- 触发时机:使用对象进行运算相加的时候自动触发
- 功能:对象运算
- 参数:二个对象参数
- 返回值:运算后的值
其他类似方法如下(了解)
- __sub__(self, other) 定义减法的行为:-
- __mul__(self, other) 定义乘法的行为:*
- __truediv__(self, other) 定义真除法的行为:/
- ...
示例
class MyClass1():
def __init__(self,num):
self.num = num
# 对象在加号+的左侧时,自动触发
def __add__(self,other):
# print(self)
# print(other)
return self.num + other # return 10 + 7 = 17
# 对象在加号+的右侧时,自动触发
def __radd__(self,other):
# print(self)
# print(other)
return self.num * 2 + other
(1)第一种
1 a = MyClass1(10)
2 res = a + 7
3 print(res)
(2)第二种
1 b = MyClass1(5)
2 res = 20 + b
3 print(res)
(3)第三种
1 res = a+b
2 print(res) #20
代码解析
- 第一次触发魔术方法, a+ =>触发__add__方法
- self => a other => b
- self.num + other => a.num+ b => 10 + b
- res = 10 + b
- 第二次触发魔术方法 __radd__
- self => b other=> 10
- self.num * 2 + other => b.num*2 + other => 5 * 2 + 10 => 20
- res = 20
六.__len__ 魔术方法
- 触发时机:使用len(对象)的时候自动触发
- 功能:用于检测对象中或者类中成员的个数
- 参数:一个self接受当前对象
- 返回值:必须返回整型
类似的还有如下等等(了解)
- __iter__(self) 定义迭代容器中的元素的行为
- __reversed__(self) 定义当被 reversed() 调用时的行为
- __contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
- ...
(1)len(obj) => 返回类中自定义成员的个数
class MyClass(): pty1 = 1 pty2 = 2 __pty3 = 3 pyt3 =10 pty100 = 90 def func1(): pass def __func2(): pass def __func3(): pass def __len__(self): lst = [] dic = MyClass.__dict__ # 方法一 """ # print(MyClass.__dict__) # print(object.__dict__) dic = MyClass.__dict__ for i in dic: if not(i.startswith("__") and i.endswith("__")): lst.append(i) return len(lst) """ # 方法二 lst = [i for i in dic if not(i.startswith("__") and i.endswith("__"))] return len(lst) obj = MyClass() print(len(obj))
七.与类相关的魔术属性
示例
class Man(): pass class Woman(): pass class Children(Man,Woman): """ 功能: 描述小孩天生的属性 成员属性:eye , skin 成员方法:skylight , moonread , __makebaby """ eye = "万花筒血轮眼" skin = "白色" def skylight(self): print("宇智波家族的小孩,天生能够发动天照技能") def moonread(self,func): # func = func111 print("宇智波家族的小孩,能够发动月亮的光照消灭你~") res = func.__name__ print(res,type(res)) def __makebaby(self): print("这一手招数,只能我自己用")
(1)__dict__ 获取对象或类的内部成员结构
1 obj = Children() 2 print(obj.__dict__) 3 print(Children.__dict__)
(2)__doc__ 获取对象或类的内部文档
1 print(obj.__doc__) 2 print(Children.__doc__)
(3)__name__ 获取类名函数名
<1>获取函数名
1 def func111(): 2 print("我是func111方法") 3 obj.moonread(func111)
<2>获取类名
obj.moonread(Man)
(4)__class__ 获取当前对象所属的类
print(obj.__class__)
(5)__bases__ 获取一个类直接继承的所有父类,返回元组
print(Children.__bases__)