欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

一些内置的魔术方法

程序员文章站 2022-03-18 16:08:34
一些内置的魔术方法: ......

一些内置的魔术方法:

一些内置的魔术方法

   
    1. __new__  :
        
        什么时候执行?在init之前
        为什么要有,用来做什么的?  用来创建一个对象需要的空间的
        单例模式(默写)
        
        【1】 实例化的时候:__new__和__init__的关系:
             先创建一块对象的空间,有一个类指针能指向类 -->由 __new__完成
             然后调用init --> __init__
                
            class a:
                def __new__(cls, *args, **kwargs):   # __new__是构造方法,通过__new__创建一块对象所占用的空间。
                    o = super().__new__(cls)   #使用父类的new
                    #或 o = object.__new__(cls)      #使用父类的new
                    print('执行new',o)#执行new <__main__.a object at 0x0000028c86f57e80>
                    return o
                def __init__(self):  #调用__init__的时候自动的把返回值o 给了self。
                    print('执行init',self)#执行init <__main__.a object at 0x0000028c86f57e80>
            a()
            #一般不用写__new__,因为写也是继承object的__new__ ,不实现的话也是默认调用object的__new__
            
        #设计模式:共23种
        【2】面试会考:
            (1)单例模式:一个类 从头到尾 只会创建一次self的空间。实例化可以多次,但空间是用同一个
            class baby:
                __instance = none  #类似flag
                def __new__(cls, *args, **kwargs):
                    if cls.__instance is none:
                        cls.__instance = super().__new__(cls)
                    return cls.__instance
                def __init__(self,cloth,pants):  #cls.__instance 返回给 self
                    self.cloth = cloth
                    self.pants = pants
            b1 = baby('红毛衣','绿皮裤') # self 返回给 b1
            print(b1.cloth,b1.pants)#红毛衣 绿皮裤
            b2 = baby('白衬衫','黑皮裤')#b1 ,b2所在的内存空间是同一个
            print(b1.cloth,b1.pants)#白衬衫 黑皮裤
            print(b2.cloth,b2.pants)#白衬衫 黑皮裤
            
            (2)python中的单例模式:用python模块实现单例模式
            #模块的代码:单例.py
            class baby:
                def __init__(self,cloth,pants):
                    self.cloth = cloth
                    self.pants = pants

            baby = baby('红上衣','绿裤子')
            
            #当前脚本
            from 单例 import baby #不管引用多少次,都是同一个实例
            from 单例 import baby #因为在python中模块不能重复导入
            print(baby)#<单例.baby object at 0x0000014c0ba2e9b0>
            print(baby)#<单例.baby object at 0x0000014c0ba2e9b0>
            print(baby)#<单例.baby object at 0x0000014c0ba2e9b0>
      
        
    
    2. __call__ : 对象() 调用这个类中的__call__方法
        
        callable(对象) : 对象 + () 能不能运行就是callable判断的事儿。对象是不是可调用,就看对象所在的类中有没有实现__call__方法

        class a:
            pass
        obj = a()
        print(callable(obj))#false
        obj()#typeerror: 'a' object is not callable


        class a:
            def __call__(self, *args, **kwargs):   #对象 + () 调用的是__call__方法下面对应的逻辑
            print('-------')

        obj = a()
        print(callable(obj))#true
        obj()#-------
        a()()#-------
        # flask框架的源码中就用到了__call__
        
    3.__len__  : 要想len(对象) ,需要在对象所在的这个类中实现__len__方法。  len()函数能不能计算对象的长度,就看对象所在的类中有没有__len__方法
         #引入:
        class cls: #班级
            def __init__(self,name):
                self.name = name
                self.students = []
            def len(self):
                return len(self.students)

        py22 = cls('py22')
        py22.students.append('相玺')
        py22.students.append('庄博')
        py22.students.append('大壮')
        print(py22.len())#3
        
        #1: len()函数能不能计算对象的长度,就看对象所在的类中有没有__len__方法
        class cls: #班级
            def __init__(self,name):
                self.name = name
                self.students = []
            def __len__(self):    #对象所在的类中有__len__方法
                return len(self.students)
        py22 = cls('py22')
        py22.students.append('相玺')
        py22.students.append('庄博')
        py22.students.append('大壮')
        print(len(py22))#3   #len()内置函数查看一个对象的长度,是因为len()在内部就调用了这个对象所在类的__len__
        
        #2:例:类比理解
        class pow:
            def __init__(self,n):
                self.n = n
            def __pow2__(self):
                return self.n ** 2

        def pow2(obj):  #自定义函数,在函数内部调用对象obj对应的类中的__pow2__
            return obj.__pow2__()
        
        obj = pow(10)  #实例化一个对象
        
        print(pow2(obj))#100
        
        #例:
        l = [1,2,3,4]
        print(l.__len__())#4
        print(len(l))#4

        
    4.__str__  : 帮助我们在打印\展示对象的时候更直观的显示对象内容 %s str() print()
                 只能 return 字符串类型
       
    #1.引入:
        class course:
            def __init__(self,name,price,period):
                self.name = name
                self.price = price
                self.period = period

        python = course('python',21800,'6 months')
        linux = course('linux',19800,'5 months')
        mysql = course('mysql',12800,'3 months')
        go = course('go',15800,'4 months')
        lst = [python,linux,mysql,go]
        for index,c in enumerate(lst,1):
            print(index,c)
        #1 <__main__.course object at 0x0000017d9d06e828>
        #2 <__main__.course object at 0x0000017d9d06e898>
        #3 <__main__.course object at 0x0000017d9d06e8d0>
        #4 <__main__.course object at 0x0000017d9d06e908>
        num = int(input('>>>'))
        course = lst[num-1]
        print('恭喜您选择的课程为 %s  价格%s元'%(course.name,course.price))
    
    #2.__str__   只能 return 字符串,不能是其他数据类型
        class course:
            def __init__(self,name,price,period):
                self.name = name
                self.price = price
                self.period = period
            def __str__(self): #帮助我们在打印\展示对象的时候更直观的显示对象内容,而不是内存地址
                return ','.join([self.name,str(self.price),self.period]) #只能return字符串
        python = course('python',21800,'6 months')
        linux = course('linux',19800,'5 months')
        mysql = course('mysql',12800,'3 months')
        go = course('go',15800,'4 months')

        lst = [python,linux,mysql,go]
        for index,c in enumerate(lst,1):
            print(index,c)
        #1 python,21800,6 months
        #2 linux,19800,5 months
        #3 mysql,12800,3 months
        #4 go,15800,4 months
        num = int(input('>>>'))
        course = lst[num-1]
        print('恭喜您选择的课程为 %s  价格%s元'%(course.name,course.price))
    
    #3:
        【1】 在打印一个对象的时候 调用__str__方法
        【2】 在%s拼接一个对象的时候 调用__str__方法
        【3】 在str一个对象的时候 调用__str__方法
    
        class clas:
            def __init__(self):
                self.student = []
            def append(self,name):
                self.student.append(name)
            def __str__(self):
                return str(self.student)

        py22 = clas()
        py22.append('大壮')
        print(py22)#['大壮']  在打印一个对象的时候 调用__str__方法
        print(str(py22))#['大壮']  在str一个对象的时候 调用__str__方法
        print('我们py22班: %s'%py22)#我们py22班: ['大壮']  在%s拼接一个对象的时候 调用__str__方法
      

        py22.append('大毛')
        print(py22)#['大壮', '大毛']
        
   

    5.__repr__ : repr是str的备胎,同时还和%r和repr有合作关系
        
         (0)当我们打印一个对象 用%s进行字符串拼接 或者str(对象)总是调用这个对象的__str__方法
         (1)如果找不到__str__,就调用__repr__方法。
         (2)__repr__不仅是__str__的替代品,还有自己的功能。
         (3)用%r进行字符串拼接 或者 用repr(对象)的时候总是调用这个对象的__repr__方法

        
    【1】
        class clas:
            def __init__(self):
                self.student = []
            def append(self,name):
                self.student.append(name)
            def __str__(self):
                return 'aaa'

        py22 = clas()
        py22.append('大壮')
        print(py22)#aaa
        print(str(py22))#aaa
        print('我们py22班 %s'%py22)#我们py22班 aaa
        print('我们py22班 %r'%py22)#我们py22班 <__main__.clas object at 0x000001ecf815e978>
        print(repr(py22))#<__main__.clas object at 0x000001ecf815e978> #没有repr还是打印内存地址

   【2】
        class clas:
            def __init__(self):
                self.student = []
            def append(self,name):
                self.student.append(name)
            def __repr__(self):
                return str(self.student)

        py22 = clas()
        py22.append('大壮')
        print(py22)#['大壮']
        print(str(py22))#['大壮']
        print('我们py22班 %s'%py22)#我们py22班 ['大壮']
        print('我们py22班 %r'%py22)#我们py22班 ['大壮']
        print(repr(py22))#['大壮']
    
  【3】
        class clas:
            def __init__(self):
                self.student = []
            def append(self,name):
                self.student.append(name)
            def __repr__(self):
                return str(self.student)
            def __str__(self):
                return 'aaa'

        py22 = clas()
        py22.append('大壮')
        print(py22)#aaa
        print(str(py22))#aaa
        print('我们py22班 %s'%py22)#我们py22班 aaa
        print('我们py22班 %r'%py22)#我们py22班 ['大壮']
        print(repr(py22))#['大壮']
        

    6.__enter__:
        

    7. __exit__ :
        

    8.__eq__   :
        

    9.__del__  :