目录
面向对象高阶
isinstance 和issubclass
- isinstance()
判断是否为实例化对象
isinstance中第一个参数为对象,第二个参数为类,isinstance不仅可以检测对象是否为类的实例化对象,同时如果第二个参数是实例化对象的类的父类时,返回结果也为True
isinstance和type的区别:
- isinstance:判断对象是否为这个类实例化出来的,或者这个类是否为实例化对象的父类.isinstance会检测父类
- type:获取实例化对象的类,通过==比较运算符进行判断,不会去检测父类
- issubclass()
判断一个类是否为另一个类的子类,第一个参数是子类,第二个参数是父类
反射
反射就是通过字符串来操作类或者对象的属性
反射的本质就是在使用内置函数,其中反射有一下四个内置函数
- hasattr:判断一个方法是否存在这个类中
- getattr:根据字符串去获取对象里面对应的方法,加括号就可以执行
- setattr:通过setattr修改属性,或者添加到对象中
- delattr:删除
__call__
__call__方法是由对象加()或者类加()()触发的,call函数定义在类体代码中定义格式为
def __call__(self,*args,**kwargs):
print()
元类metaclass
什么是元类
元类就是负责制造类,也就是说元类是类的类
元类-->元类实例化-->类-->类实例化-->对象
使用/自定义元类的目的就是为了控制类产生的过程,还可以控制对象产生的过程
class创建类
如果说类也是对象,那么用class关键字的创建类的过程也是一个实例化的过程,该实例化的目的就是为了得到一个类,调用的是元类
用class关键字创建一个类,用的默认的元类type
# 类名 class_nameclass_name='Foo'# 类体代码 class_bodyclass_body='''count=0country='china'def __init__(self,name): self.name=namedef f1(self): print('f1 from Foo')'''# 父类 class_basesclass_bases=(object,)# exec方法(运行第一个参数的中的代码,把产生的名字丢入第三个参数字典中)class_dic=dict{}exec(class_body,{},class_dic)# 使用type生成类 type(类名,基类,类的名称空间)Foo=type(class_name,classs_bases,class_dic)
- 分析用class自定义类运行原理(而非元类的运行原理)
- 拿到一个字符串格式的类名 class_name
- 拿到一个类的基类名 class_bases=(object,)
- 执行类体代码,拿到一个类的名称空间class_dic={...}
- 调用Foo=type(class_name,class_bases,class_dic)
自定义元类控制类的创建
class Mymeta(type): #继承type类的类才能称之为元类 def __init__(self.class_name,class_bases,class_dic): super().__init__(class_name,class_bases,class_dic)#使用父类type的功能,创建元类
- 自定义元类控制类的产生过程,类的产生过程其实就是原理的调用过程
- 我们可以在自定义元类的init方法中加入一些限制,来控制类的产生
class Mymeta(type): #继承type类的类才能称之为元类 def __init__(self.class_name,class_bases,class_dic): if not class_dict.get('__doc__'): raise TypeError('类中必须有文档注释') if not class_name.istitle(): raise TypeError('类名首字母必须大写') super().__init__(class_name,class_bases,class_dic)#使用父类type的功能,创建元类
加上元类后类的属性查找顺序
对象本身-->类-->父类-->父类-->object-->元类(metaclass)-->type-->找不到就报错