python面向对象之魔术方法(特定时机自动触发) 魔术属性
触发时机:实例化对象,初始化的时候触发
功能:为对象添加成员
参数:参数不固定,至少一个self参数
返回值:无
# (1) 基本语法 class MyClass(): def __init__(self): print("构造方法被触发 ... ") self.color = "屎黄色" # 实例化对象 obj = MyClass() print(obj.__dict__) print(obj.color) # (2) 带有多个参数的构造方法 class MyClass(): def __init__(self,color): self.color = color # 实例化对象 obj1 = MyClass("狗屎绿") print(obj1.color) obj2 = MyClass("粉嫩红") print(obj2.color) # (3)类可以是一个,对象可以是多个,创造的对象彼此是独立的; class Children(): def __init__(self,name,skin): self.name = name self.skin = skin def cry(self): print("小孩一下生久哇哇哇的哭") def la(self): print("小孩一下生久拉粑粑") def __eat(self): print("小孩一下生就要吃奶奶..") def info(self): print("小孩的名字:{},小孩的肤色{}".format(self.name,self.skin)) def info2(self,name,skin): print("小孩的名字:{},小孩的肤色{}".format(name,skin)) # 实例化对象 afanda = Children("阿凡达","深蓝色") afanda.cry() afanda.info() haoke = Children("绿巨人","绿色的") haoke.la() haoke.info() wangbaoqiang = Children("王宝强","亮绿色") wangbaoqiang.info() # wangbaoqiang.__eat() error wangbaoqiang.info2("张保张","黄色")
__new__ 魔术方法
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
参数:至少一个cls接受当前的类,其他根据情况决定
返回值:通常返回对象或None
(1) 基本使用
class MyClass2(): a = 100 obj2 = MyClass2() # print(obj2) class MyClass1(): def __new__(cls): # print(cls) # 1.返回本类对象 """类.成员方法(类)""" # return object.__new__(cls) # 2.返回其他类的对象 # return obj2 # 3.不返回对象,None return None obj = MyClass1() # print(obj.a) print(obj)
(2) __new__ 触发时机要快于 __init__
""" __new__ 创建对象 __init__ 初始化对象 """ class MyClass(): def __new__(cls): print(1) return object.__new__(cls) def __init__(self): print(2) obj = MyClass()
(3) __new__的参数要和__init__参数一一对应
class Boat(): def __new__(cls,name): return object.__new__(cls) def __init__(self,name): self.name = name obj = Boat("万里阳光号") print(obj.name)
使用收集参数进行改造
class Boat(): # *args,**kwargs 可以收集多余的所有参数 def __new__(cls,*args,**kwargs): return object.__new__(cls) def __init__(self,name,type): self.name = name self.type = type obj = Boat("万里阳光号","破木头做的") print(obj.name , obj.type)
(4) __new__和__init__之间的注意点
如果__new__ 没有返回对象或者返回的是其他类的对象,不会调用构造方法.
只有在返回自己本类对象的时候,才会调用构造方法.
class Children(): def __new__(cls,*args,**kwargs): return obj2 # pass def __init__(self,name,skin): print("构造方法被触发 ... ") # self.name = name # self.skin = skin obj = Children("灭霸","紫薯") # print(obj.name) error # print(obj.skin) error
__del__ 魔术方法(析构方法)
触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无
(1) 基本语法
class Lion(): def __init__(self,name): self.name = name def __del__(self): print("析构方法被触发 ... ") # 触发方式一: 页面执行完毕回收所有变量 obj1 = Lion("辛巴") # 触发方式二: 所有对象被del的时候 obj2 = obj1 obj3 = obj1 print(obj2 , obj1 ,obj3) print("<====start===>") del obj1 del obj2 del obj3 print("<====end===>")
(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 __del__(self): self.fp.close() # 读取文件 def readcontent(self): return self.fp.read() obj = ReadFile("0.py") print(obj.readcontent())
__str__ 魔术方法
触发时机: 使用print(对象)或者str(对象)的时候触发
功能: 查看对象
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
class Cat(): gift = "抓老鼠" def __init__(self,name): self.name = name def cat_gift(self): return "小猫叫{},小猫会{}".format(self.name,self.gift) def __str__(self): return self.cat_gift() __repr__ = __str__ tom = Cat("汤姆") # 触发时机1 : print(对象) # print(tom) # 触发时机2 : str(对象) res = str(tom) print(res) print("<==================>") res = repr(tom) print(res , type(res)) print("<==================>")
__repr__ 魔术方法
触发时机: 使用repr(对象)的时候触发
功能: 查看对象,与魔术方法__str__相似
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
class Mouse(): gift = "偷油吃" def __init__(self,name): self.name = name def mouse_gift(self): return "老鼠叫{},老鼠会{}".format(self.name,self.gift) def __repr__(self): return self.mouse_gift() # 系统底层默认把__repr__方法赋值给__str__方法,所以通过print或者str强转可以触发; # __str__ = __repr__ jerry = Mouse("杰瑞") # res = repr(jerry) # print(res) # 可以触发 # print(jerry) res = str(jerry) print(res)
__call__ 魔术方法
触发时机:把对象当作函数调用的时候自动触发
功能: 模拟函数化操作
参数: 参数不固定,至少一个self参数
返回值: 看需求
(1) 基本语法
class MyClass(): def __call__(self): print("__call__魔术方法被触发 ... ") obj = MyClass() obj()
(2) 利用__call__魔术方法做统一调用
class Wash(): def __call__(self,something): print("我要洗{}".format(something)) self.step1(something) self.step2() self.step3() return "洗完了" def step1(self,something): print("放水,把{}扔进去".format(something)) def step2(self): print("倒洗衣粉,洗衣液,蓝月亮,金纺,立白 ... ") def step3(self): print("洗一洗,晾干,穿上") obj = Wash() # obj.step1() # obj.step2() # obj.step3() res = obj("袜子") print(res)
(3) 模拟整型强转操作
import math class MyInt(): def __call__(self,num): if isinstance(num,bool): if num == False: return 0 else: return 1 elif isinstance(num,int): return num elif isinstance(num,float): # 方法一 # a,b = str(num).split(".") # return eval(a) # 方法二 """ 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 elif num[0] == "-": sign = -1 # 截取符号后面的字符串传递 return self.calc(num[1:],sign) elif num.isdecimal(): return self.calc(num) else: return "这个算不了兄弟~" # 计算最后的数值 def calc(self,num,sign=1): # 去掉前面的"0"字符串 num = num.lstrip("0") # print(num , type(num) , "<==============>") if num == "": return 0 return eval(num) * sign myint = MyInt() res = myint(-5.67) print(res , type(res)) res = myint("-000000000000055555") print(res , type(res)) res = myint("asdfasdfasdfasdf") print(res , type(res)) # print(myint("+0000000000000")) # bool int float 纯数字字符串 # int(3.78) => 3 # print(int(-3.78)) # import math # print(math.floor(0) ) # => 3 # print(math.ceil(0)) """ print( int("00000000000001223") ) # 1223 print( int("-00000000000001223") ) # -1223 print( int("+00000000000001223") ) # 1223 print( int("+0000000000000") ) # 1223 """ # print( int("asdfasdfasdfasdf") ) # 1223 # print( eval("00000000000001223") ) # print( eval("+00000000000001223") ) # print( eval("-00000000000001223") ) # print( eval("-00000000000001223abc") )
----普通变量的基本操作,如果应用在对象上,也有相应的魔术方法
__bool__ 魔术方法
触发时机:使用bool(对象)的时候自动触发
功能:强转对象
参数:一个self接受当前对象
返回值:必须是布尔类型
类似的还有如下等等(了解):
__complex__(self) 被complex强转对象时调用
__int__(self) 被int强转对象时调用
__float__(self) 被float强转对象时调用
...
...
基本语法
class MyClass(): def __bool__(self): return True obj = MyClass() print(bool(obj))
__add__ 魔术方法 (与之相关的__radd__ 反向加法)
触发时机:使用对象进行运算相加的时候自动触发
功能:对象运算
参数:二个对象参数
返回值:运算后的值
类似的还有如下等等:
__sub__(self, other) 定义减法的行为:-
__mul__(self, other) 定义乘法的行为:
__truediv__(self, other) 定义真除法的行为:/
...
...
基本语法
class MyClass(): def __init__(self,num): self.num = num # 当对象在 + 号的左侧时,自动触发 def __add__(self,other): # print(self) # print(other) return self.num * 3 + other def __radd__(self,other): # print(self) # 对象 # print(other) # 7 return self.num * 5 + other # add的触发方式 a = MyClass(3) res = a + 1 print(res) # radd的触发方式 b = MyClass(5) res = 7 + b print(res) # 对象 + 对象 res = a + b print(res) """ a+b 触发的是add魔术方法 self 接受的是a other 接受的是b return a.num + b => return 9 + b res = 9 + b 触发的是radd魔术方法 self 接受的是b other 接受的是9 return b.num * 5 + 9 => 5 * 5 + 9 => 34 """
__len__ 魔术方法
触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中某个内容的个数
参数:一个self接受当前对象
返回值:必须返回整型
类似的还有如下等等(了解):
__iter__(self) 定义迭代容器中的元素的行为
__reversed__(self) 定义当被 reversed() 调用时的行为
__contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
...
...
len(对象) => 类中的所有自定义成员
class MyClass(): pty1 = 1 pty2 = 2 __pty3 = 3 def func1(): pass def func2(): pass def __func3(): pass def __len__(self): # 以__开头并且以__结尾的成员过滤掉; return len( [ i for i in MyClass.__dict__ if not ( i.startswith("__") and i.endswith("__") ) ] ) obj = MyClass() print(len(obj)) """ 代码原型; print(MyClass.__dict__) lst = [] for i in MyClass.__dict__: print(i , type(i)) if not ( i.startswith("__") and i.endswith("__") ): lst.append(i) print(len(lst)) """ """ { '__module__': '__main__', 'pty1': 1, 'pty2': 2, '_MyClass__pty3': 3, 'func1':, 'func2': """, '_MyClass__func3': , '__len__': , '__dict__': , '__weakref__': , '__doc__': None }
魔术属性
class Man(): pass class Woman(): pass class Sasuke(Man,Woman): """ 描述: 佐助这个的天生属性,技能 成员属性: __eye skin 成员方法: skylight __moonread """ __eye = "血轮眼->万花筒->轮回眼" skin = "白色" def skylight(self , myfunc): print("使用天照,一团黑色的火焰 ... 恐怖如斯") res = myfunc.__name__ print(res , type(res) ) def __moonread(self): print("使用月读,让敌人拉入到幻术空间,被施法者掌握") obj = Sasuke() # __dict__ 获取对象或类的内部成员结构 dic = Sasuke.__dict__ dic = obj.__dict__ print(dic) # __doc__ 获取对象或类的内部文档 print(Sasuke.__doc__) print(obj.__doc__) # __name__ 获取类名函数名 def func343434(): print("佩恩出场时,使用一手地爆天星,技惊四座,点燃所有观众") obj.skylight(func343434) # __class__ 获取当前对象所属的类 print(obj.__class__) # __bases__ 获取一个类直接继承的所有父类,返回元组 print(Sasuke.__bases__)