python面向对象之魔术方法(特定时机自动触发) 魔术属性

魔术方法(特定时机自动触发)

 

__init__ 构造方法

触发时机:实例化对象,初始化的时候触发
功能:为对象添加成员
参数:参数不固定,至少一个self参数
返回值:无

# (1) 基本语法
class MyClass():
    def __init__(self):
        print("构造方法被触发 ... ")
        self.color = "屎黄色"
        
# 实例化对象
obj = MyClass()
print(obj.__dict__)
print(obj.color)

# (2) 带有多个参数的构造方法
class MyClass():
    def __init__(self,color):
        self.color = color

# 实例化对象
obj1 = MyClass("狗屎绿")
print(obj1.color)
obj2 = MyClass("粉嫩红")
print(obj2.color)

# (3)类可以是一个,对象可以是多个,创造的对象彼此是独立的;
class Children():
    def __init__(self,name,skin):
        self.name = name
        self.skin = skin
    
    def cry(self):
        print("小孩一下生久哇哇哇的哭")
    
    def la(self):
        print("小孩一下生久拉粑粑")
        
    def __eat(self):
        print("小孩一下生就要吃奶奶..")
    
    def info(self):
        print("小孩的名字:{},小孩的肤色{}".format(self.name,self.skin))
        
    def info2(self,name,skin):
        print("小孩的名字:{},小孩的肤色{}".format(name,skin))


# 实例化对象
afanda = Children("阿凡达","深蓝色")
afanda.cry()
afanda.info()

haoke = Children("绿巨人","绿色的")
haoke.la()
haoke.info()

wangbaoqiang = Children("王宝强","亮绿色")
wangbaoqiang.info()
# wangbaoqiang.__eat() error
wangbaoqiang.info2("张保张","黄色")
View Code

 

__new__ 魔术方法

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

 

(1) 基本使用

class MyClass2():
    a = 100
obj2 = MyClass2()
# print(obj2)

class MyClass1():
    def __new__(cls):
        # print(cls)        
        # 1.返回本类对象
        """类.成员方法(类)"""
        # return object.__new__(cls)
        # 2.返回其他类的对象
        # return obj2
        # 3.不返回对象,None
        return None        
    
obj = MyClass1()
# print(obj.a)
print(obj)
View Code

(2) __new__ 触发时机要快于 __init__

"""
__new__  创建对象
__init__ 初始化对象
"""
class MyClass():

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

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

(3) __new__的参数要和__init__参数一一对应

class Boat():
    def __new__(cls,name):
        return object.__new__(cls)
    
    def __init__(self,name):
        self.name  = name

obj = Boat("万里阳光号")
print(obj.name)
View Code

使用收集参数进行改造

class Boat():
    # *args,**kwargs 可以收集多余的所有参数
    def __new__(cls,*args,**kwargs):
        return object.__new__(cls)
    
    def __init__(self,name,type):
        self.name  = name
        self.type = type

obj = Boat("万里阳光号","破木头做的")
print(obj.name , obj.type)
View Code

(4) __new__和__init__之间的注意点

如果__new__ 没有返回对象或者返回的是其他类的对象,不会调用构造方法.
只有在返回自己本类对象的时候,才会调用构造方法.

class Children():
    def __new__(cls,*args,**kwargs):
        return obj2
        # pass
        
    def __init__(self,name,skin):
        print("构造方法被触发 ... ")
        # self.name = name
        # self.skin = skin
        
obj = Children("灭霸","紫薯")

# print(obj.name) error
# print(obj.skin) error
View Code

 

 

__del__ 魔术方法(析构方法)

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

(1) 基本语法

class Lion():
    def __init__(self,name):
        self.name = name
        
    def __del__(self):
        print("析构方法被触发 ... ")

# 触发方式一: 页面执行完毕回收所有变量
obj1 = Lion("辛巴")

# 触发方式二: 所有对象被del的时候
obj2 = obj1
obj3 = obj1
print(obj2 , obj1 ,obj3)
print("<====start===>")
del obj1
del obj2
del obj3
print("<====end===>")
View Code

(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 __del__(self):
        self.fp.close()
        
    # 读取文件
    def readcontent(self):
        return self.fp.read()
        

obj = ReadFile("0.py")
print(obj.readcontent())
View Code

 

__str__ 魔术方法

触发时机: 使用print(对象)或者str(对象)的时候触发
功能: 查看对象
参数: 一个self接受当前对象
返回值: 必须返回字符串类型

class Cat():
    gift = "抓老鼠"
    def __init__(self,name):
        self.name = name
        
    def cat_gift(self):
        return "小猫叫{},小猫会{}".format(self.name,self.gift)
    
    def __str__(self):
        return self.cat_gift()    

    __repr__ = __str__
    
tom = Cat("汤姆")
# 触发时机1 :  print(对象)
# print(tom)
# 触发时机2 :  str(对象)
res = str(tom)
print(res)

print("<==================>")
res = repr(tom)
print(res , type(res))
print("<==================>")
View Code

 

__repr__ 魔术方法

触发时机: 使用repr(对象)的时候触发
功能: 查看对象,与魔术方法__str__相似
参数: 一个self接受当前对象
返回值: 必须返回字符串类型

class Mouse():
    gift = "偷油吃"
    def __init__(self,name):
        self.name = name
    
    def mouse_gift(self):
        return "老鼠叫{},老鼠会{}".format(self.name,self.gift)
    
    def __repr__(self):
        return self.mouse_gift()
    
    # 系统底层默认把__repr__方法赋值给__str__方法,所以通过print或者str强转可以触发;
    # __str__ = __repr__
    
jerry = Mouse("杰瑞")
# res = repr(jerry)
# print(res)

# 可以触发
# print(jerry)
res = str(jerry)
print(res)
View Code

 

__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(something)
        self.step2()
        self.step3()
        return "洗完了"
        
    def step1(self,something):
        print("放水,把{}扔进去".format(something))
        
    def step2(self):
        print("倒洗衣粉,洗衣液,蓝月亮,金纺,立白 ... ")
        
    def step3(self):
        print("洗一洗,晾干,穿上")

obj = Wash()
# obj.step1()
# obj.step2()
# obj.step3()
res = obj("袜子")
print(res)
View Code

 

 (3) 模拟整型强转操作

import math
class MyInt():
    def __call__(self,num):
        if isinstance(num,bool):
            if num == False:
                return 0 
            else:
                return 1
                
        elif isinstance(num,int):
            return num
            
        elif isinstance(num,float):
            # 方法一
            # a,b = str(num).split(".")
            # return eval(a)
            
            # 方法二
            """
            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
                elif num[0] == "-":
                    sign = -1    
                # 截取符号后面的字符串传递
                return self.calc(num[1:],sign)
                
            elif num.isdecimal():
                return self.calc(num)
            else:
                return "这个算不了兄弟~"

        
    # 计算最后的数值
    def calc(self,num,sign=1):
        # 去掉前面的"0"字符串
        num    = num.lstrip("0")
        # print(num , type(num) , "<==============>")
        if num == "":
            return 0 
        
        return eval(num) * sign            
            
    
myint = MyInt()
res = myint(-5.67) 
print(res , type(res))
res = myint("-000000000000055555")
print(res , type(res))
res = myint("asdfasdfasdfasdf")
print(res , type(res))
# print(myint("+0000000000000"))
# bool int  float 纯数字字符串

# int(3.78) => 3
# print(int(-3.78))
# import math
# print(math.floor(0) ) # => 3
# print(math.ceil(0))

"""
print(    int("00000000000001223")   )  # 1223
print(    int("-00000000000001223")   ) # -1223
print(    int("+00000000000001223")   ) # 1223
print(    int("+0000000000000")   ) # 1223
"""
# print(    int("asdfasdfasdfasdf")   ) # 1223
# print(  eval("00000000000001223")   )
# print(  eval("+00000000000001223")   )
# print(  eval("-00000000000001223")   )
# print(  eval("-00000000000001223abc")   )
View Code

 

----普通变量的基本操作,如果应用在对象上,也有相应的魔术方法

__bool__ 魔术方法

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

 

类似的还有如下等等(了解):
__complex__(self) 被complex强转对象时调用
__int__(self) 被int强转对象时调用
__float__(self) 被float强转对象时调用
...
...

 

基本语法

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

 

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

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

 

类似的还有如下等等:
__sub__(self, other)          定义减法的行为:-
__mul__(self, other)          定义乘法的行为:
__truediv__(self, other)     定义真除法的行为:/
...
...

 基本语法

class MyClass():
    def __init__(self,num):
        self.num = num
        
    # 当对象在 + 号的左侧时,自动触发
    def __add__(self,other):
        # print(self)
        # print(other)
        return self.num * 3 + other
        
    def __radd__(self,other):
        # print(self)  # 对象
        # print(other) # 7
        return self.num * 5 + other
        
# add的触发方式
a = MyClass(3)
res = a + 1
print(res)

# radd的触发方式
b = MyClass(5)
res = 7 + b
print(res)

# 对象 + 对象
res = a + b
print(res)

"""
a+b 触发的是add魔术方法  self 接受的是a   other 接受的是b
return a.num + b  => return 9 + b
res =  9 + b   触发的是radd魔术方法  self 接受的是b   other 接受的是9
return b.num * 5 + 9  => 5 * 5 + 9 => 34
"""
View Code

 

__len__ 魔术方法

触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中某个内容的个数
参数:一个self接受当前对象
返回值:必须返回整型

 

类似的还有如下等等(了解):
__iter__(self) 定义迭代容器中的元素的行为
__reversed__(self) 定义当被 reversed() 调用时的行为
__contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
...
...

 

len(对象) => 类中的所有自定义成员

 

class MyClass():
    pty1 = 1
    pty2 = 2 
    __pty3 = 3
    
    def func1():
        pass
    def func2():
        pass
    def __func3():
        pass
        
    def __len__(self):
        # 以__开头并且以__结尾的成员过滤掉;
        return len( [  i for i in MyClass.__dict__ if not (  i.startswith("__") and i.endswith("__")  )  ] ) 

obj = MyClass()
print(len(obj))


"""
代码原型;
print(MyClass.__dict__)
lst = []
for i in MyClass.__dict__:
    print(i , type(i))
    if not (  i.startswith("__") and i.endswith("__")  ):
        lst.append(i)
print(len(lst))
"""

"""

{
'__module__': '__main__', 
'pty1': 1, 
'pty2': 2, 
'_MyClass__pty3': 3, 
'func1': <function MyClass.func1 at 0x7f6898431378>, 
'func2': <function MyClass.func2 at 0x7f6898431400>, 
'_MyClass__func3': <function MyClass.__func3 at 0x7f6898431488>, 
'__len__': <function MyClass.__len__ at 0x7f6898431510>, 
'__dict__': <attribute '__dict__' of 'MyClass' objects>, 
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
 '__doc__': None
 }
"""
View Code

 

 

魔术属性

class Man():
    pass

class Woman():
    pass

class Sasuke(Man,Woman):
    """
描述: 佐助这个的天生属性,技能
成员属性:  __eye skin
成员方法: skylight __moonread
    """
    __eye = "血轮眼->万花筒->轮回眼"
    
    skin = "白色"
    
    def skylight(self , myfunc):
        print("使用天照,一团黑色的火焰 ... 恐怖如斯")
        res = myfunc.__name__
        print(res , type(res) )
        
    def __moonread(self):
        print("使用月读,让敌人拉入到幻术空间,被施法者掌握")

obj = Sasuke()
# __dict__ 获取对象或类的内部成员结构
dic = Sasuke.__dict__
dic = obj.__dict__
print(dic)

# __doc__  获取对象或类的内部文档
print(Sasuke.__doc__)
print(obj.__doc__)

# __name__  获取类名函数名
def func343434():
    print("佩恩出场时,使用一手地爆天星,技惊四座,点燃所有观众")

obj.skylight(func343434)

# __class__ 获取当前对象所属的类
print(obj.__class__)

# __bases__ 获取一个类直接继承的所有父类,返回元组
print(Sasuke.__bases__)
View Code

 

posted @ 2022-03-30 23:38  帅童学  阅读(232)  评论(0编辑  收藏  举报