一些内置的魔术方法
程序员文章站
2022-06-19 12:41:37
一些内置的魔术方法: ......
一些内置的魔术方法:
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__ :