一、__new__方法
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
参数:至少一个cls接受当前的类,其他根据情况决定
返回值:通常返回对象或None
1.基本语法
class MyClass():
a = 1
obj = MyClass()
print(obj)
class MyClass1(object):
def __new__(cls):
print(cls)
# (1)借助父类object 类.方法(),返回本类自己的对象
# obj = object.__new__(cls)
# return obj
# (2)返回其他类的对象
# return obj
# (3)不返回任何对象
return None
obj = MyClass1()
print(obj)
2.new方法的触发时机要快于init
new 用来创建对象
init 用来初始化对象(前提的有对象)
先创建对象,再去初始化对象,所以new快于init
class Boat():
def __init__(self):
print(2)
def __new__(cls):
print(1)
return object.__new__(cls)
obj = Boat()
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():
def __new__(cls,*args,**kwargs):
return object.__new__(cls)
def __init__(self,name,a,b,c,d,e):
self.name = name
obj = Boat("泰坦尼克号",2,3,4,5,6)
print(obj.name)
4.如果返回的不是本类的对象,不会触发__init__构造方法
print("<=====>")
class MyClass():
a = 1
other_obj = MyClass()
class Boat():
def __new__(cls):
return other_obj
def __init__(self):
print("构造方法被触发~")
obj = Boat()
二、单例(态)模式
目的意义:
为了节省内存空间,仅仅是为了调用类中的成员,
不需要额外给该对象添加任何成员,这个场景,使用单态.
比如:操作数据库的增删改查这样的类,是不需要的.
1.基本语法
class Singleton():
__obj = None
def __new__(cls):
if cls.__obj is None:
cls.__obj = object.__new__(cls)
return cls.__obj
"""
<__main__.Singleton object at 0x000001FB3F207278>
有这个对象直接返回,没这个对象,就给你创建,保证只有一个
第一次实例化时,if cls.__obj is None 条件为真 , 创建一个对象放到cls.__obj , 最后返回
第二次实例化时,if cls.__obj is None 条件为假 , 直接返回
第三次实例化时,if cls.__obj is None 条件为假 , 直接返回
第三次实例化时,if cls.__obj is None 条件为假 , 直接返回
"""
obj1 = Singleton()
print(obj1)
obj2 = Singleton()
print(obj2)
obj3 = Singleton()
print(obj3)
obj4 = Singleton()
print(obj4)
# 打印结果为同一个对象
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("aaa")
obj2 = Singleton("bbb")
# 求答案
print(obj1.name)
print(obj2.name)
# obj1 和 obj2 都是同时指向同一个对象,因为对象只创建了一个对象.name 是获取他后边bbb那个值,是同一个值打印了2次;
三、__del__析构方法
触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无
1.基本方法
del只会触发一次,即如果先把所有的对象给删除了,那么在执行完所有代码之后不会再触发
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)
print("<==start==>")
del obj
del other_obj
print("<==end==>")
2.模拟文件操作练习
将文件操作也封装起来,这要其他同事在使用文件操作时候,只需要调用我们写的代码就可以了,减少了代码冗余
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):
# 读取文件操作
content = self.fp.read()
return content
def __del__(self):
self.fp.close()
obj = ReadFile("ceshi.txt")
res = obj.readcontent()
print(res)
四、__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,self.gift)
tom = Cat("汤姆")
# 触发方式一, print 打印该对象
print(tom)
# 触发方式二, str
res = str(tom)
print(res)
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)
# 在系统底层,如果定义了repr , 将会默认赋值给str方法.
# __str__ = __repr__
# repr强转obj对象时触发
obj = Mouse("杰瑞")
res = repr(obj)
print(res)
# 注意点 底层存在赋值调用给str的语法,所以能实现打印或者str强转对象的触发机制.
print(obj)
res = str(obj)
print(res)
五、__call__方法
触发时机:把对象当做函数调用时候自动触发
功能:模拟函数化操作
参数:参数不固定,至少一个self参数
返回值:看需求
1.基本用法
class MyClass():
a = 1
""""""
def __call__(self):
print("call魔术方法被触发..")
obj = MyClass()
obj()
2.call魔术方法的应用
# 模拟洗衣服的过程
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("裤衩")
obj("衣服")
obj("袜子")
obj("毛巾")
# 如不使用魔术方法,我们每次洗衣服都需要调三个函数
obj.step1("裤衩")
obj.step2()
obj.step3()
obj.step1("衣服")
obj.step2()
obj.step3()
obj.step1("袜子")
obj.step2()
obj.step3()
obj.step1("毛巾")
obj.step2()
obj.step3()
3.模拟内置函数int
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:
return "老铁,这个真不能转~"
六、__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)
七、__add__方法
触发时机:使用对象进行运算相加的时候自动触发
功能:对象运算
参数:两个对象参数
返回值:运算后的值(其中的运算规则可以自己定制)
类似的还有如下(了解):
__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)
res = a + 7
print(res)
# self 接受a other接受7 , 触发的是__add__方法
# 情况二
a = MyAdd(7)
res = 7 + a
print(res)
# self 接受a other接受7 , 触发的是__radd__方法
# 情况三
a = MyAdd(7)
b = MyAdd(8)
res = a+b
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
'''
八、__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))
九、__getattr__方法
基本语法及使用
当对象访问一个不存在的属性时候,会触发该方法。
class Student:
def __init__(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age
def __getattr__(self,x):
return '你没有这个属性,小老弟'
s = Student('yang','male',18)
print(s.name)
print(s.salary)
------------------
yang
你没有这个属性,小老弟
十、魔术属性
以__开头__结尾的属性,称为魔术属性,如之前ATM项目中使用到的__name__就是魔术属性.
本笔记记录常用的五种魔术属性,dict,doc,name,class,bases
class Man():
pass
class Woman():
pass
class Children(Man,Woman):
"""
成员属性: eye
成员方法: skylight moonread __makebaby
完成的功能: 描述宇智波一族的天赋技能.
"""
eye = "血轮眼"
def skylight(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__)
# __doc__ 获取对象或类的内部文档
print(obj.__doc__)
print(Children.__doc__)
# __name__ 获取类名函数名
def earth_boom():
print("使出一招地爆天星")
obj.moonread(earth_boom)
obj.moonread(Children)
# __class__ 获取当前对象所属的类
print(obj.__class__)
# __bases__ 获取一个类直接继承的所有父类,返回元组
print(Children.__bases__) # (<class '__main__.Man'>, <class '__main__.Woman'>)