一 .__new__ 魔术方法
''' 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值:通常返回对象或None '''
1.基本使用
class OtherClass(): pty = 200 obj2 = OtherClass() class MyClass(): pty = 1 def __new__(cls): print('__new__方法被触发') print('cls') print('<=========>') # 返回本类对象 (借父生子) # 类.方法(cls) # return object.__new__(cls) # 不返回对象 # return None # 返回其他类对象 return obj2 obj = MyClass() print(obj) print(obj.pty)
2.__new__ 和 __init__ 的触发时机
""" __new__是在造对象时触发 __init__有对象之后,初始化对象的时候自动触发 现有对象,在初始化 """
class MyClass(): def __new__(cls): print(111) return object.__new__(cls) def __init__(self): print(222) # 实例化对象 obj = MyClass()
3.__new__ 和 __init__ 参数需要一一对应
class MyClass(): def __new__(cls,name): print(333) return object.__new__(cls) def __init__(self,name): print(444) self.name = name obj = MyClass("李琦") print(obj.name) # 在__new__中加上收集参数,以不变应万变 class MyClass(): def __new__(cls,*args,**kwargs): print(333) return object.__new__(cls) def __init__(self,name,sex,age): print(444) self.name = name self.sex = sex self.age = age obj = MyClass("朱培峰","女性","100") print(obj.name) print(obj.sex) print(obj.age)
4.注意点
""" 如果没有创建对象,不会触发构造方法 如果返回的不是本类对象,不会触发构造方法 """
class MyClass(): def __new__(cls): print("__new__方法被触发 ... ") # return None return obj2 def __init__(self): print("构造方法被触发 ... ") obj = MyClass() print(obj)
二 单态模式
同一个类,无论实例化多少次,都有且只有一个对象;
""" 作用: 可以减少内存空间的浪费,提升代码执行效率 场景:如果不需要在创建对象时,在类外额外为当前添加成员,就可以使用单态模式 """
(1) 基本使用
class SingleTon(): # 类中私有成员属性 __obj = None def __new__(cls): print(cls) # 类.私有成员属性 if cls.__obj is None: # 存储创建的对象在私有成员__obj当中 # 类.私有成员属性 = 值(对象) cls.__obj = object.__new__(cls) #返回该对象 return cls.__obj obj1 = SingleTon() obj2 = SingleTon() obj3 = SingleTon() print(obj1) print(obj2) print(obj3)
(2) 注意点
class SingleTon(): __obj = None def __new__(cls,*args,**kwargs): if cls.__obj is None: cls.__obj = object.__new__(cls) return cls.__obj def __init__(self,name): self.name = name obj1 = SingleTon("王永娟") obj2 = SingleTon("荷叶") print(obj1.name) print(obj2.name) print(obj1,obj2) print(obj1 is obj2) """ # 代码解析: 第一次,创建一个对象 obj1 赋值name数据为王永娟 self.name = 王永娟 print(obj1.name ) 王永娟 第二次,创建一个对象 obj2 赋值name数据为荷叶 self.name = 荷叶 print(obj2.name ) 荷叶 因为print是一起打印的; name = "王永娟" name = "荷叶" print(name) 所以打印后者; """
三 __del__ 魔术方法(析构方法)
''' 触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候] 功能:对象使用完毕后资源回收 参数:一个self接受对象 返回值:无 '''
1.基本使用
class LangDog(): # 构造方法 def __init__(self,name): self.name = name # 析构方法 def __del__(self): print("析构方法被触发 ... ") # 1.页面执行完毕回收所有变量,自动触发 obj1 = LangDog("小白土狗") print(obj1.name)
2.模拟文件操作
import os class ReadFile(): def __new__(cls,filename): # 判断文件是否存在,在创建对象 if os.path.exists(filename): return object.__new__(cls) else: print("抱歉,该文件不存在") def __init__(self,filename): # 打开文件 self.fp = open(filename,mode="r",encoding="utf-8") def readfile(self): # 读取文件 data = self.fp.read() return data def __del__(self): # 关闭文件 self.fp.close() obj = ReadFile("ceshi1.txt") # obj = ReadFile("ceshi1.txt234242234423") 文件不存在,不会创建对象 res = obj.readfile() print(res)
四 __call__ 魔术方法
''' 触发时机:把对象当作函数调用的时候自动触发 功能: 模拟函数化操作 参数: 参数不固定,至少一个self参数 返回值: 看需求 '''
(1) 基本用法
class MyClass(): 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("穿上去,等于晾干") obj = Wash() # 方法一 # obj.step1() # obj.step2() # obj.step3() # 方法二 res = obj("洗衣服") print(res)
3.模拟int操作
import math class MyInt(): 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): # 方法一 """ a,b = str(num).split(".") return eval(a) """ # 方法二 """ceil floor""" """ 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 "抱歉,这个算不了" def calc(self,num,sign=1): # print("<========================>") res = num.lstrip("0") if res == "": return 0 return eval(res) * sign # int 整型 浮点型 布尔型 纯数字字符串 myint = MyInt() # 布尔型 res = myint(False) print(res) # 整型 res = myint(199) print(res) # 浮点型 res = myint(5.77) res = myint(-5.77) print(res , type(res)) # 字符串 # res = myint("-00001111") res = myint("asdfasdf") # -1111 ("-000000000000000000000000") print("<============start============>") print(res) print("<============end============>")
五 __str__ 和 __repr__
1.__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) tom = Cat('汤姆') res = str(tom) print(res)
手动添加__repr__ = __str__ 把 str 赋值给 str 可以使用 repr()
2.__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__ jerry = Mouse("杰瑞") res = repr(jerry) print(res) # 因为系统底层赋值的原因,在打印对象或者强转对象为字符串的时候,仍然可以触发; print(jerry) res = str(jerry) print(res)
六 __bool__魔术方法
""" 触发时机: 使用bool(对象)的时候自动触发 功能: 强制对象 参数: 一个self接受当前对象 返回值: 必须是布尔类型 """
class MyClass(): def __bool__(self): return False obj = MyClass() res = bool(obj) print(res)
七 __add__魔术方法(与之相关的__redd__反向加法)
""" 触发时机: 使用对象进行运算相加的时候自动触发 功能: 对象运算 参数: 二个对象参数 返回值: 运算后的值 """
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 # 第一种 a = MyClass1(10) res = a + 7 print(res) # 第二种 b = MyClass1(5) res = 20 + b print(res) # 第三种 print("<============>") res = a+b print(res) """ 第一次触发魔术方法, 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接受当前对象 返回值: 必须返回整数 """
# 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)) """ { '__module__': '__main__', 'pty1': 1, 'pty2': 2, '_MyClass__pty3': 3, 'func1': <function MyClass.func1 at 0x7fc198171378>, 'func2': <function MyClass.func2 at 0x7fc198171400>, '_MyClass__func3': <function MyClass.__func3 at 0x7fc198171488>, '__len__': <function MyClass.__len__ at 0x7fc198171510>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None } """
九 与类相关的魔术属性
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__ 获取对象或类的内部成员结构
obj = Children() print(obj.__dict__) print(Children.__dict__)
2.__doc__ 获取对象或类的内部文档
print(obj.__doc__) print(Children.__doc__)
3.__name__ 获取类名函数名
def func111(): print("我是func111方法") # 获取函数名 obj.moonread(func111) # 获取类名 obj.moonread(Man)
4.__class__ 获取当前对象所属的类
print(obj.__class__)
5.__bases__ 获取一个类直接继承的所有父类,返回元组
print(Children.__bases__)