day19-Python运维开发基础(类的魔术方法)

1. __new__魔术方法

# ###  __new__ 魔术方法
'''
    触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
    功能:控制对象的创建过程
    参数:至少一个cls接受当前的类,其他根据情况决定
    返回值:通常返回对象或None
'''

class MyClass2():
    b = 2
obj2 = MyClass2()

# (1) 基本语法
"""
借助object父类中的__new__魔术方法,创建对象
需要传递cls这个参数,代表的是本类,为本类创建对象,进行返回
"""
class MyClass():
    a = 1
    def __new__(cls):
        print(cls) # <class '__main__.MyClass'>
        # 借助父类object,里面的__new__魔术方法创建对象
        # 1.返回本对象
        return object.__new__(cls)
        # 2.返回其他类的对象
        # return obj2
        # 3.不返回任何对象
        # return None
        
        
obj = MyClass()    
print(obj)    
# 返回本对象
# print(obj.a)
# 返回其他类对象
# print(obj.b)

# (2) 验证__new__和__init__两个方法的触发时间
"""
__new__  用来创建对象
__init__ 用来初始化对象的
先创建在初始化
__new__ 触发时机快于__init__
"""

class MyClass():
    def __new__(cls):
        print(1)
        return object.__new__(cls)

    def __init__(self):
        print(2)    
        
obj = MyClass()

# 传一个参数的情况
class MyClass():
    def __new__(cls,name):
        return object.__new__(cls)

    def __init__(self,name):
        self.name = name
        
obj = MyClass("周永玲")

# 传多个参数的情况
class MyClass():
    # 多个参数下,用收集参数来保证形参实参一一对应
    def __new__(cls,*args,**kwargs):
        return object.__new__(cls)
        
    def __init__(self,name,skin,age):
        self.name = name
        self.skin = skin
        self.age = age
obj = MyClass("周玲玲","绿色",108)
print(obj.name)

# 注意点:
"""
如果__new__返回的不是自己本类的对象,不会触发构造方法__init__
"""
class MyClass():

    def __new__(cls,*args,**kwargs):
        print("__new__被触发")
        return obj2
        
    def __init__(self):
        print("__init__构造方法被触发")
obj = MyClass()
__new__魔术方法 示例代码
# ### 单态模式 : 无论实例化对象多少次,都有且只有一个对象

# (1) 基本语法
"""为了节省空间,加快效率,提出单态模式"""
class Singleton():
    __obj = None
    def __new__(cls):
        if cls.__obj is None:
            cls.__obj = object.__new__(cls)
        return cls.__obj

"""
第一次实例化的时候,cls.__obj is None 返回True
执行object.__new__(cls) 返回对象 让cls.__obj接受对象
return 该对象

第二次实例化的时候,cls.__obj is None 返回False
return cls.__obj 内存中堆空间存放的对象返回

第三次实例化的时候,cls.__obj is None 返回False
return cls.__obj 内存中堆空间存放的对象返回

以后 .. 每次进行实例化的对象,都是第一次存储的那个对象
就实现了无论实例化几次,都返回同一个对象;
"""

obj1 = Singleton()
obj2 = Singleton()
obj3 = Singleton()
print(obj1,obj2,obj3)
print(obj1 is obj2)

# (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)

"""

第一次实例化的时候, self.name = 李诗韵
第一次实例化的时候, 返回的是第一次实例化出来的对象
将该对象以前的name属性 从李诗韵改成黄乐西
self.name = 黄乐西

打印 obj1.name  obj2.name 都是黄乐西

"""
单态模式 示例代码

2. 类的魔术方法

 

# ### 魔术方法 __del__ (析构方法)
'''
    触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
    功能:对象使用完毕后资源回收
    参数:一个self接受对象
    返回值:无
'''

# (1) 基本使用
class Dog():
    def __init__(self,name):
        self.name = name
        
    def eatmeat(self):
        print("小狗喜欢吃肉包子")
    
    def __del__(self):
        print("析构方法被触发")

# (1)页面执行完毕回收所有变量
obj = Dog("詹姆斯·蛋蛋")
obj.eatmeat()

# (2)所有对象被del的时候
"""
两个变量指向同一个对象,其中删除obj这个变量的指向关系,
还有一个变量在指向该对象,所以对象没有被删除,不能够触发析构方法__del__
"""
obj2 = obj
print("===start===")
del obj
# del obj2
print("===end====")

# (3)读取文件操作
import os
"""
fp = open("文件名",mode="r",encoding="utf-8")
res = fp.read()
fp.close()
"""
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 readfile(self):
        res = self.fp.read()
        return res
    
    # 关闭文件
    def __del__(self):
        self.fp.close()

obj = ReadFile("ceshi.txt")
res = obj.readfile()
print(res)
__del__析构方法 示例代码
# ###__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()
        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()
"""
# 方法二
# obj()
res = obj("洗衣服")
print(res)


# 模拟int方法,自定义类
import math
"""bool int float 字符串"""
class MyInt():
                    
    def myfunc(self,num,sign=1):
        # print(num)
        # print(sign)
        res = num.lstrip("0")
        if res == "":
            return 0        
        return eval(res) * sign

    def __call__(self,n):
    
        # 判断是不是bool
        if isinstance(n,bool):
            if n == True:
                return 1
            else:
                return 0
                
        # 判断是不是int
        elif isinstance(n,int):
            return n
            
        # 判断是不是float
        elif isinstance(n,float):
            if n > 0:
                return math.floor(n)
            else:
                return math.ceil(n)
                
        # 判断是不是字符串
        elif isinstance(n,str):
            
            # 判断是否带符号 + - 
            if (n[0] == "+" or n[0] == "-") and n[1:].isdecimal():                
                sign = None
                # 获取符号
                if n[0] == "+":
                    sign = 1
                elif n[0] == "-":
                    sign = -1
                return self.myfunc(n[1:],sign)
            # 判断是否是纯数字字符串
            elif n.isdecimal():
                return self.myfunc(n)
            else:
                return "老弟,这个东西算不了."
                
        else:
            return "脑弟,这个算不了"
            

myint = MyInt()
res = myint(True)
res = myint(-19.89)
# res = myint("-abcddfdf")
# res = myint([1,2,3])
print(res,type(res))
__call__魔术方法 示例代码
# ### __str__ 魔术方法
'''
    触发时机: 使用print(对象)或者str(对象)的时候触发
    功能:     查看对象
    参数:     一个self接受当前对象
    返回值:   必须返回字符串类型
'''

class Cat():
    gift = "卖萌,喵喵喵"
    def __init__(self,name):
        self.name = name
        
    def cat_info(self):
        return "小猫的名字{},小猫的天赋{}".format(self.name,self.gift)
        
    def __str__(self):
        return self.cat_info()

    
tom = Cat("汤姆")
# 方法一
print(tom)
# 方法二
res = str(tom)
print(res)

# ### __repr__ 魔术方法
'''
    触发时机: 使用repr(对象)的时候触发
    功能:     查看对象,与魔术方法__str__相似
    参数:     一个self接受当前对象
    返回值:   必须返回字符串类型
'''
class Mouse():
    gift = "偷油吃,下不来"
    def __init__(self,name):
        self.name = name
        
    def mouse_info(self):
        return "小老鼠名字{},天赋{}".format(self.name,self.gift)
        
    def __repr__(self):
        return self.mouse_info()
        
    # 在系统底层默认加了如下一句话
    # __str__ = __repr__

jerry = Mouse("杰瑞")
res = repr(jerry)
print(res)

print(jerry)
res = str(jerry)    
print(res)
    
__str__魔术方法 示例代码
# ### __bool__ 魔术方法
'''
    触发时机:使用bool(对象)的时候自动触发
    功能:强转对象
    参数:一个self接受当前对象
    返回值:必须是布尔类型
'''
class MyClass():
    def __bool__(self):
        return False

obj = MyClass()
res = bool(obj)
print(res)

#__add__ 魔术方法  (与之相关的__radd__ 反向加法)
'''
    触发时机:使用对象进行运算相加的时候自动触发
    功能:对象运算
    参数:二个对象参数
    返回值:运算后的值
'''

class MyClass():
    def __init__(self,num):
        self.num = num
    
    """对象在 加号+ 的左侧时,自动触发"""
    def __add__(self,other):
        print("add方法被触发")
        """
        self 接受的是obj对象
        other 接受的是数字
        """
        # print(self)
        # print(other)
        return self.num + other
    
    """对象在 加号+ 的右侧时,自动触发"""
    def __radd__(self,other):
        """
        self 接受的是对象b
        other 接受的是3
        """
        return self.num + other * 3 # 5 + 3 * 3 = 14

# (1) add 方法
a = MyClass(10)
res = a + 1
print(res)

# (2) radd方法
b = MyClass(5)
res = 3 + b
print(res)

# (3) 对象 + 对象
"""
先触发add方法
self  接受a
other 接受b
return self.num + other => return 10 + b
res = 10 + b

后触发radd方法
self  接受b
other 接受10
return self.num + other * 3 => 5 + 10 *3 = 35
"""
res = a+b
print(res)


#__len__ 魔术方法
'''
    触发时机:使用len(对象)的时候自动触发 
    功能:用于检测对象中或者类中成员个数
    参数:一个self接受当前对象
    返回值:必须返回整型
'''
class MyClass():
    pty1 = 1
    pty2 = 2
    __pty3 = 3

    def func1():
        print(1)
    def func2():
        pass
    def __func3():
        pass
        
    def __len__(self):
        dic = MyClass.__dict__
        print(dic)
        """
        {
        '__module__': '__main__', 
        'pty1': 1, 'pty2': 2, '_MyClass__pty3': 3, 
        'func1': <function MyClass.func1 at 0x7f99d664f6a8>, 
        'func2': <function MyClass.func2 at 0x7f99d664f730>, 
        '_MyClass__func3': <function MyClass.__func3 at 0x7f99d664f7b8>, 
        '__len__': <function MyClass.__len__ at 0x7f99d664f840>, 
        '__dict__': <attribute '__dict__' of 'MyClass' objects>, 
        '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 
        '__doc__': None
        }
        """
        # 方法一
        """
        lst = []
        for i in dic:
            if not( i.startswith("__") and i.endswith("__") ):
                lst.append(i)
        print(lst)
        """
        # 方法二
        lst = [ i for i in dic if not( i.startswith("__") and i.endswith("__") )]        
        return len(lst)
        

obj = MyClass()
res = len(obj)
print(res)
__bool / add / len 魔术方法 __ 示例代码

day19

原文地址:https://www.cnblogs.com/reachos/p/12177422.html