魔术方法 init, new, del ,call
1. init 构造方法
# __init__ 魔术方法(构造方法)
"""
魔术方法:
系统自动调用的方法,按照触发机制调用
"""
# __init__ : 构造方法
"""
触发机制 : 实例化对象,初始化时触发
功能 : 为对象添加成员
参数 : 至少一个self参数
返回值: 无
"""
# 1.基本使用
class Class():
def __init__(self):
print("构造方法被触发")
self.name="熊大"
obj = Class() #实例化对象,init被触发
print(obj.__dict__) #查看obj对象成员 {'name': '熊大'}
print(obj.name) #熊大
# 2.带有参数的构造方法
"""
在实例化对象时,给予构造方法参数
"""
# 传入一个参数
class Class():
def __init__(self,name):
self.name=name
obj = Class("贾英贺") #实例化传参
print(obj.__dict__) #{'name': '贾英贺'}
print(obj.name) #贾英贺
# 传入多个参数
class People():
def __init__(self,name,skin):
self.name=name
self.skin=skin
def info(self):
print("姓名:{},肤色:{}".format(self.name,self.skin))
obj = People("舒畅","黄色")
print(obj.__dict__) #{'name': '舒畅', 'skin': '黄色'}
obj.info() #姓名:舒畅,肤色:黄色
2. new 魔术方法
# __new__魔术方法
"""
触发时机 : 实例化类生成对象的时候触发(触发时机在__init__构造方法之前)
功能: 控制对象的创建过程
参数 : 至少一个cls接收当前的类(cls是本类),其他根据情况决定
返回值 : 通常返回对象或None
"""
# 1.基本使用
"""
return 返回啥,obj就是啥
"""
class Class():
pty=1
def __new__(cls):
print("new被触发")
obj = Class()
print(obj) # 没有返回值obj就是None
class Class():
pty=1
def __new__(cls):
print("new被触发")
return 22
obj = Class()
print(obj) # 22 返回什么就是什么
class Class():
pty=1
def __new__(cls):
print("new被触发")
return object.__new__(cls)
obj = Class()
print(obj) # 借助父类产生本类对象
print(obj.pty) #1
class M():
pty=111
obj1 = M()
class Class():
pty=1
def __new__(cls):
print("new被触发")
return obj1
obj = Class()
print(obj) # 还可以返回其他类对象
print(obj.pty) #111
# 2.__new__和__init__的触发时机
"""
__new__ 是在创造对象时触发
__init__ 是在有本类对象后,初始化本类对象的时触发
先有对象,才能初始化对象
"""
class Me():
def __init__(self):
print("init被触发")
def __new__(cls):
print("new被触发")
return object.__new__(cls)
obj = Me() #new触发后,init才被触发
# 3.__new__和__init__的参数需要一一对应 否则报错
class My():
def __new__(cls,name):
return object.__new__(cls)
def __init__(self,name):
self.name=name
obj = My("光头强")
print(obj.name) #光头强
# 解决办法 : 可以在__new__中加上收集参数,以不变应万变
class A():
def __new__(cls,*args,**kwargs)
return object.__new__(cls)
def __init__(self,name,sex):
self.name=name
self.sex=sex
obj = A("小强","男")
print(obj.name)
print(obj.sex)
2.1 单态模式
# 单态模式:同一个类,无论实例化多少次,都有且只有一个对象
"""
作用 : 可以减少内存空间的浪费,提升代码执行效率
应用场景: 如果不需要在创建对象时,在类外为当前对象添加成员,就可以使用单态模式
"""
class Me():
__obj=None
def __new__(cls):
if cls.__obj is None: #关键字最好用is判断,虽==也可以
cls.__obj = object.__new__(cls)
# 使用类调用属性更改了成员属性
return cls.__obj
obj1=Me()
obj2=Me()
print(obj1) #<__main__.Me object at 0x7f8153681470>
print(obj2) #<__main__.Me object at 0x7f8153681470>
"""无论实例化多少次,内存地址是一样的,都是第一个实例化对象地址"""
# 注意点
class Me():
__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=Me("光头强")
obj2=Me("熊大")
print(obj1.name) #熊大
print(obj2.name) #熊大
print(obj1.__dict__) #{'name': '熊大'} 查看对象中成员
print(obj2.__dict__) #{'name': '熊大'}
"""
obj1和obj2地址一样,指向是一个对象,
对象中成员self.name 第二次赋值把第一次覆盖了
所以打印的是最后一次赋值结果
"""
3. del 析构方法
# __del__魔术方法(析构方法)
"""
触发时机: 当对象被内存回收的使用自动触发
1.页面执行完毕自动回收所有变量
2.所有对象都被del删除的时候
功能: 对象使用完毕后资源回收
参数: 一个self 接收参数
返回值: 无
"""
# 1.基本使用
class J():
def __init__(self,name): #构造方法
self.name=name
def __del__(self): #析构方法
print("析构方法被触发")
# 1.页面执行完毕自动回收所有变量
obj=J("光头强") #析构方法被触发
# 2.所有的对象都被del删除的时候
"""
注意: 当一个数据没有被任何变量引用的时候,才会真正的被内存释放掉
"""
obj1=obj
print("--------")
del obj
del obj1 #析构方法被触发
print("--------")
# 2.模拟文件操作
import os
class ReadFile():
def __new__(cls,filename):
if os.path.exists(filename): #判断文件是否存在 用isfile也可以
return object.__new__(cls)
else:
print("文件不存在")
def __init__(self,filename):
self.fp=open(filename,mode="r",encoding="utf-8") #打开文件
def read(self):
return self.fp.read() #读取文件
def __del__(self):
self.fp.close() #关闭文件
obj = ReadFile("lianxi.txt")
print(obj.read()) #读取文件
4. call 魔术方法
# __call__魔术方法
"""
触发时机: 把对象当成函数调用的时候自动触发
功能: 模拟函数化操作
参数: 参数不固定,至少一个self参数
返回值: 看需求
"""
# 1.基本用法
class Me():
def __call__(self):
print("call 被触发")
obj = Me()
obj()
# 2.模拟洗衣过程
class Wash():
def step1(self):
print("衣服扔进洗衣机")
def step2(self):
print("加洗衣液")
def step3(self):
print("晾干")
def __call__(self,something):
print(something)
self.step1()
self.step2()
self.step3()
return "洗完了"
obj = Wash()
res = obj("洗衣服")
print(res)
# 3.模拟int强转操作
import math
class Int():
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)
"""
# 方法二: 利用math模块,向上向下取整
"""
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 == "": #是否为空字符串
return "这个算不了"
else:
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):
res = num.lstrip("0")
if res == "":
return 0
return eval(res) * sign
obj = Int()
res = obj("") #这个算不了
print(res)
res = obj("000221") #221
print(res)