zoukankan      html  css  js  c++  java
  • day25:7个魔术方法&5个关于类的魔术属性

    目录

    1.__del__(析构方法)

    2.魔术方法:__str__

    3.魔术方法:__repr__

    4.魔术方法:__call__

    5.魔术方法:__bool__

    6.魔术方法:__add__&__radd__

    7.魔术方法:__len__

    8.与类相关的魔术属性

    一个小表格方便记忆哈

    __del__ (析构方法)

    __del__简要介绍

    1.触发时机:当对象被内存回收的时候自动触发

      (1)页面执行完毕回收所有变量

      (2)所有对象被del的时候

    2.功能:对象使用完毕后资源回收

    3.参数:一个self接受对象

    4.返回值:

    第一种情况:页面执行完毕回收所有变量

    class LangDog():
        food = "改吃蔬菜"
    
        def __init__(self, name):
            self.name = name
    
        def __del__(self):
            print("析构方法被触发")
    print("0001=====")
    obj = LangDog("肉丝")
    print("0002=====")
    # 1.页面执行完毕回收所有变量
    print(obj.name) # 当执行完这句话后,才算页面执行完毕,这个时候触发__del__析构方法
    
    '''
    运行结果:
    =====
    =====
    肉丝
    析构方法被触发
    '''

    第二种情况:所有对象被del的时候

    如何理解第二种情况中所说到的所有对象

    代码如下:

    class LangDog():
        food = "改吃蔬菜"
    
        def __init__(self, name):
            self.name = name
    
        def __del__(self):
            print("析构方法被触发")
    
    obj1 = LangDog("肉丝")
    obj2 = obj1
    print("<=====start=====>")
    del obj1
    print("<=====end=====>")

    打印结果:

    虽然obj1对象被删除了,但是obj2对象并没有被删除,所以不会触发析构方法

    打印了“析构方法被触发”是因为整个页面执行完毕了,也会触发析构方法

    使用__del__模拟文件操作

    # 3.模拟文件操作
    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):
            # 读取文件
            return self.fp.read()
        
        def __del__(self):
            # 关闭文件
            self.fp.close()
        
    obj = ReadFile("1.txt")
    
    if obj is not None:
        res = obj.readcontent()
        print(res)
    else:
        print("没有该类文件")
    
    
    # 当然,也可以用三元运算符来实现
    """ 真值 if 条件表达式 else 假值 """
    print(obj.readcontent()) if obj is not None else print("没有该类文件")

    魔术方法:__str__

    __str__简要介绍

    1.触发时机: 使用print(对象)或者str(对象)的时候触发

    2.功能: 查看对象

    3.参数: 一个self接受当前对象

    4.返回值: 必须返回字符串类型

    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,5000)
        
        # __repr__ = __str__
        
    tom = Cat("汤姆")
    # 方法一. print(对象)
    print(tom)
    # 方法二. str(对象)
    res = str(tom)
    print(res)

    魔术方法:__repr__

    1.触发时机: 使用repr(对象)的时候触发

    2.功能: 查看对象,与魔术方法__str__相似

    3.参数: 一个self接受当前对象

    4.返回值: 必须返回字符串类型

    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)

    魔术方法:__call__

    1.触发时机:把对象当作函数调用的时候自动触发

    2.功能: 模拟函数化操作

    3.参数: 参数不固定,至少一个self参数

    4.返回值: 看需求

    基本用法

    # (1) 基本用法
    class MyClass():
        a = 1
        def __call__(self):
            print("call魔术方法被触发了")
    
    obj = MyClass() # 实例化一个对象
    obj() # 把对象当做函数调用,此时会触发__call__方法

    模拟洗衣服的过程

    # (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("衣服") # 把对象obj当做函数进行调用,此时触发__call__方法,执行__call__方法所有内容
    print(res)

    模拟内置的int方法,实现相应的操作(有时间再分析)

    # (3) 模拟内置int 实现相应的操作
    import math
    class MyInt():
    
        def calc(self,num,sign=1):
            # print(num,sign)
            
            # 去掉左边多余的0
            strvar = num.lstrip("0")
            # print(strvar)
            
            # 为了防止都是0 ,如果去掉之后为空,返回0
            if strvar == "":
                return 0
            
            # 正常情况下,执行存数字字符串变成数字 , 在乘上相应的符号,得出最后的结果
            return eval(strvar) * sign
    
        def __call__(self,num):
            if isinstance(num , bool):
                if num  == True:
                    return 1
                elif num == False:                
                    return 0
                    
            elif isinstance(num,int):
                return num
                
            elif isinstance(num,float):
                # 方法一
                """
                strvar = str(num)
                lst = strvar.split(".")
                return eval(lst[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.calc(num[1:],sign)
                    
                elif num.isdecimal():
                    return self.calc(num)
                else:
                    return "老铁,这个真转不了"
            
    
    myint = MyInt()
    # myint(5) => 5
    # myint(3.14) => 3
    
    res = myint(True)
    print(res)
    res = myint(100)
    print(res)
    res = myint(3333.14)
    print(res, type(res)) # 3
    # bool int float "12312312323"
    
    
    # int(3.14) => 3
    print(int(3.14))  # 3
    print(int(-3.14)) # -3
    print("<===>")
    print(myint(3.14))
    print(myint(-0.2))
    
    print("<===>")
    print(int("0000000000000000000000000000000000000000001230000000"))
    print(int("00000000000000000000000000000000000000000"),"1111222333")
    print(int("+000000000000000000000000000000000000000000123"))
    print(int("-000000000000000000000000000000000000000000123"))
    print(int("000000000000000000000000000000000000000000123"))
    
    print("<==111=>")
    print(myint("+000000000234"))
    print(myint("000000000000000000000000000000000000000000123"))
    print(myint("456899200"))
    print(myint("3.143434"))
    print(myint(+-++-+-+-+-+-+-+-+-+-+-++++++++-----234234),"<====>")
    print(int(+-++-+-+-+-+-+-+-+-+-+-++++++++-----234234),"<====>")
    
    """
    exec("a = 3")
    print(a)
    
    eval("4")
    """
    # print(math.floor(0.14)) # 0
    # print(math.floor(3.14)) # 3
    # print(math.ceil(-3.14))  # -3

    魔术方法:__bool__

    __bool__简要介绍

    1.触发时机:使用bool(对象)的时候自动触发

    2.功能:强转对象

    3.参数:一个self接受当前对象

    4.返回值:必须是布尔类型

    class MyClass():
        def __bool__(self):
            return False
        
    obj = MyClass()
    res = bool(obj)
    print(res)

    类似的还有如下等等(了解):

    __complex__(self) 被complex强转对象时调用

    __int__(self) 被int强转对象时调用

    __float__(self) 被float强转对象时调用

    ...

    ...

    魔术方法:__add__,__radd__

    __add__简要介绍

    1.触发时机:使用对象进行运算相加的时候自动触发

    2.功能:对象运算

    3.参数:二个对象参数

    4.返回值:运算后的值

    5.注意点:

      对象在加号+的左侧时,自动触发__add__方法

      对象在加号+的右侧时,自动触发__radd__方法

      加号左侧和右侧都是对象时,先触发__add__方法,再触发__radd__方法

    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 
    """

    类似的还有如下等等(了解):

    __sub__(self, other) 定义减法的行为:-

    __mul__(self, other) 定义乘法的行为:*

    __truediv__(self, other) 定义真除法的行为:/
    ...
    ...

    魔术方法:__len__

    __len__简要介绍

    1.触发时机:使用len(对象)的时候自动触发

    2.功能:用于检测对象中或者类中成员的个数

    3.参数:一个self接受当前对象

    4.返回值:必须返回整型

    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)

    与类相关的魔术属性

    __dict__ 获取对象或类的内部成员结构

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

    __name__ 获取类名函数名

    __class__ 获取当前对象所属的类

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

    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("这一手招数,只能我自己用")
        
        
    
    # __dict__ 获取对象或类的内部成员结构
    obj = Children()
    print(obj.__dict__)
    print(Children.__dict__)
    
    
    # __doc__  获取对象或类的内部文档
    print(obj.__doc__)
    print(Children.__doc__)
    
    # __name__ 获取类名函数名
    def func111():    
        print("我是func111方法")
    # 获取函数名
    obj.moonread(func111)
    # 获取类名
    obj.moonread(Man)
    
    # __class__ 获取当前对象所属的类
    print(obj.__class__)
    
    # __bases__ 获取一个类直接继承的所有父类,返回元组
    print(Children.__bases__)
  • 相关阅读:
    mysql 的安装
    nginx的安装
    修改网站默认目录
    配置yum仓库 安装httpd服务
    安装 VMware Tools
    phpstrom + xdebug 断点调试
    公网IP访问服务器
    mysql in操作和find_in_set函数
    网页授权有时候获取不到openid 的坑
    解决Required Integer parameter 'id' is not present的一种方法
  • 原文地址:https://www.cnblogs.com/libolun/p/13449103.html
Copyright © 2011-2022 走看看