万事开头难

1.__new__ 魔术方法 单态(例)模式 __del__ 魔术方法(析构方法) __call__ 魔术方法

一 .__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)
View Code

 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)
View Code

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)
View Code

(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)
View Code

四 __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============>")
View Code

 五 __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__)
View Code

2.__doc__ 获取对象或类的内部文档

print(obj.__doc__)
print(Children.__doc__)
View Code

3.__name__ 获取类名函数名

def func111():    
    print("我是func111方法")
# 获取函数名
obj.moonread(func111)
# 获取类名
obj.moonread(Man)
View Code

4.__class__ 获取当前对象所属的类

print(obj.__class__)
View Code

5.__bases__ 获取一个类直接继承的所有父类,返回元组

print(Children.__bases__)
View Code

 

posted @ 2021-01-17 15:44  Bo7-w  阅读(100)  评论(0编辑  收藏  举报