欢迎来到十九分快乐的博客

生死看淡,不服就干。

4.魔术方法1-init-new-del-call

魔术方法 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)
posted @ 2020-12-17 20:31  十九分快乐  阅读(39)  评论(0编辑  收藏  举报