8.06_python_lx_day25

一.魔术方法

(1)__del__ 魔术方法(析构方法)

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

示例

class LangDog():
    food = "改吃蔬菜"
    def __init__(self,name):
        self.name = name
    def __del__(self):
        print("析构方法被触发")        

<1>页面执行完毕回收所有变量

1 obj = LangDog("肉丝")
2 print(obj.name)#最后一行代码结束后,析构方法被触发

<2>所有对象被del的时候

1 obj = LangDog("肉丝")
2 other_obj = obj
3 print("<=====start=====>")
4 del obj
5 del other_obj    #对象全部被删除后,析构方法被触发
6 print("<=====end=====>")

<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("属性_反射.md")
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__ 魔术方法

  • 触发时机: 使用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,5000)

  __repr__ = __str__

<1>方法一. print(对象)

tom = Cat("汤姆")
print(tom)#触发__str__返回字符串

<2>方法二. str(对象)

res = str(tom)#触发__str__返回字符串用res接收
print(res)#打印返回的字符串

<3>小扩展 让repr强转对象时,触发打印内容

tom = Cat("汤姆")
res = repr(tom)# 类中 添加__repr__ = __str__
print(res)

三.__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__

<1>方法一. print(对象)

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

<2>方法二. str(对象)

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

<3>因为系统底层赋值的原因,在打印对象或者强转对象为字符串的时候,仍然可以触发

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

三.__call__ 魔术方法

  • 触发时机:把对象当作函数调用的时候自动触发
  • 功能: 模拟函数化操作
  • 参数: 参数不固定,至少一个self参数
  • 返回值: 看需求

(1) 基本用法

class MyClass():
    a = 1
    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("脱水,穿上")

<1>方法一

1 obj = Wash()
2 obj.step1()#加热水,家洗衣粉,加洗衣液,加洗涤剂
3 obj.step2()#衣服泡进去搅乱 打散 搓一搓~ 
4 obj.step3()#脱水,穿上

<2>方法二

1 obj = Wash()
2 res = obj("衣服")
3 print(res)'''我现在要洗衣服
4 加热水,家洗衣粉,加洗衣液,加洗涤剂
5 衣服泡进去搅乱 打散 搓一搓~ 
6 脱水,穿上
7 洗完了
8 '''

(3) 模拟内置int 实现相应的操作

import math
class MyInt():
    def calc(self,num,sign=1):
        # 去掉左边多余的0
        strvar = num.lstrip("0")
        # 为了防止都是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()
print(myint(True))
print(myint(100))
print(myint(3333.14))
print(myint("+000000000234"))
print(myint("3.143434"))
print(myint("000000000000000000000000000000000000000000123"))

四.__bool__ 魔术方法

  • 触发时机:使用bool(对象)的时候自动触发
  • 功能:强转对象
  • 参数:一个self接受当前对象
  • 返回值:必须是布尔类型

其他类似方法如下(了解)

  • __complex__(self) 被complex强转对象时调用
  • __int__(self) 被int强转对象时调用
  • __float__(self) 被float强转对象时调用
  • ...

示例

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

五.__add__ 魔术方法  (与之相关的__radd__ 反向加法)

  • 触发时机:使用对象进行运算相加的时候自动触发
  • 功能:对象运算
  • 参数:二个对象参数
  • 返回值:运算后的值

其他类似方法如下(了解)

  • __sub__(self, other) 定义减法的行为:-
  • __mul__(self, other) 定义乘法的行为:*
  • __truediv__(self, other) 定义真除法的行为:/
  • ...

示例

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

(1)第一种

1 a = MyClass1(10)
2 res = a + 7 
3 print(res) 

(2)第二种

1 b = MyClass1(5)
2 res = 20 + b
3 print(res)

(3)第三种

1 res = a+b
2 print(res) #20

代码解析

  • 第一次触发魔术方法, 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接受当前对象
  • 返回值:必须返回整型

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

  • __iter__(self) 定义迭代容器中的元素的行为
  • __reversed__(self) 定义当被 reversed() 调用时的行为
  • __contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
  • ...

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

七.与类相关的魔术属性

示例

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__ 获取对象或类的内部成员结构

1 obj = Children()
2 print(obj.__dict__)
3 print(Children.__dict__)

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

1 print(obj.__doc__)
2 print(Children.__doc__)

(3)__name__ 获取类名函数名

<1>获取函数名

1 def func111():    
2     print("我是func111方法")
3 obj.moonread(func111)

<2>获取类名

obj.moonread(Man)

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

print(obj.__class__)

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

print(Children.__bases__)

 

posted @ 2020-08-07 00:03  Magicianlx  阅读(161)  评论(0编辑  收藏  举报