1.对象的一些内置方法
#__str__:在对象被打印的时候自动触发,可以用来定义对象被打印时的输出信息 #注意:必须返回一个字符串类型的值 class People: def __init__(self,name,age): self.name=name self.age=age def __str__(self): return '<name:%s age:%s>'%(self.name,self.age) lqz=People('lqz',18) print(lqz) #__del__:在对象呗删除时先自动触发该方法,可以用来回收对象以外其他相关资源,比如系统资源 # class Foo: # def __init__(self,x,filepath,encoding='utf-8'): # self.x=x # self.f=open(filepath,'rt',encoding=encoding) # # def __del__(self): # print('run.....') # # 回收对象关联的其他资源 # self.f.close() # # obj=Foo(1,'a.txt') # # del obj # print('主===========>') #__call__:调用对象(就是对象加括号)时会调用该方法
2.元类
在python中,type和object的关系要理一下。
可以这么理解,在新式类中,object是所有类的超类。而type是object的类型,同时object又是type的超类。
可以把object和type理解成鸡生蛋,蛋生鸡的关系。
在python中,一切皆对象,而对象都是类实例化得到的
class OldboyTeacher: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) tea1=OldboyTeacher('egon',18,'male') print(type(tea1)) print(type(OldboyTeacher))
OldboyTeacher=元类(...),内置的元类是type
关系:
1.调用元类----》自定义的类
2.调用自定义的类---->自定义的对象
class关键字创建自定义类的底层工作原理,分为四步
#class关键字创建自定义类的底层工作原理,分为四步 #1.先拿到类名:'OldboyTeacher' #2.再拿到类的基类们:(object,) #3.然后拿到类的名称空间(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,补充exec) #4.调用元类实例化得到自定义的类: OldboyTeacher=type('OldboyTeacher',(object,),{...}) # class OldboyTeacher: #OldboyTeacher=type(...) # school = 'Oldboy' # def __init__(self,name,age,sex): # self.name=name # self.age=age # self.sex=sex # # def score(self): # print('%s is scoring' %self.name) # print(OldboyTeacher) #自定义类的三个关键组成部分 #1.类名 #2.类的基类们 #3.类的名称空间 #不依赖class关键字创建一个自定义类 #1.拿到类名 class_name='OldboyTeacher' #2.拿到类的基类们 class_bases=(object,) #3.拿到类的名称空间 class_dic={} path={} class_body=""" school = 'Oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) """ exec(class_body,{},class_dic) print(class_dic) #4.调用type得到自定义的类 OldboyTeacher=type(class_name,class_bases,class_dic) print(OldboyTeacher) tea=OldboyTeacher('lqz',18,'male') print(tea.__dict__)
3.自定义元类
自定义元类是有模板的,如果有自定义逻辑,拿出来修改一下就行了
#模板 class Mymeta(type):#但凡继承了type的类才能称之为自定义的元类,否则就只是一个普通的类 def __init__(self,class_name,class_bases,class_dict): super().__init__(class_name,class_bases,class_dict) print(class_name) print(class_bases) print(class_dict) class OldboyTeacher(object,metaclass=Mymeta): school='Oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring'%self.name)
自定义元类,可以控制类的产生
class MyException(BaseException): def __init__(self,msg): self.msg=msg def __str__(self): return self.msg #控制类的产生 #1.类名必须用驼峰体 #2.类体必须有文档注释 class Mymeta(type): def __init__(self,class_name,class_bases,class_dict): super().__init__(class_name,class_bases,class_dict) if class_name.islower(): raise MyException('必须使用驼峰体,傻叉') doc=class_dict.get('__doc__') if doc is None or len(doc)==0: raise TypeError('类体中必须要有注释,傻叉') class Oldboyteacher(object,metaclass=Mymeta): ' ' school = 'Oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def score(self): print('%s is scoring' % self.name) print(Oldboyteacher)
自定义元类来控制类的调用过程
#实例化OldboyTeacher,或者说调用OldboyTeacher会 #1.先产生一个空对象 #2.执行__init__方法,完成对象的初始属性操作 #3.返回初始化好的那个对象 #调用OldboyTeacher(...)就是在调用OldboyTeacher的类中的__call__,那么在__call__中就需要做上述三件事 class Mymeta(type): def __call__(self, *args, **kwargs): #1.先产生一个空对象(准备) tea_obj=self.__new__(self)#tea_obj是OldboyTeacher这个类的对象 #2.执行__init__方法,完成对象的初始属性操作 self.__init__(tea_obj,*args,**kwargs) #3.返回初始化好的那个对象 return tea_obj class OldboyTeacher(object,metaclass=Mymeta): school = 'Oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) tea=OldboyTeacher('lqz',18,'male') print(tea.__dict__)
类的属性查找顺序
先找自己继承的父类,一直找到object类,还找不到则再找自己的元类,再到type类
注意:这里查找顺序,是把OldboyTeacher当成了对象,而不是当成类看待
class Mymeta(type): # 但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类 n=444 def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类 # 1. 先产生一个空对象 tea_obj = self.__new__(self) # tea_obj是OldboyTeacher这个类的对象 # print(self.__new__ is object.__new__) # tea_obj=object.__new__(self) # 2. 执行__init__方法,完成对象的初始属性操作 self.__init__(tea_obj, *args, **kwargs) # 3. 返回初始化好的那个对象 return tea_obj class Bar: # n = 33 pass class Foo(Bar): # n = 222 pass class OldboyTeacher(Foo, metaclass=Mymeta): # OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...}) # n = 111 school = 'Oldboy' def __init__(self, name, age, sex): self.name = name #None.name='egon' self.age = age self.sex = sex def score(self): print('%s is scoring' % self.name) def __new__(cls, *args, **kwargs): # print('=====>') return super().__new__(cls) print(OldboyTeacher.n)