元类介绍
## 元类----------------> 用来实例化产生类的那个类
## 关系 : 元类---------------实例化 --------------->类----------------------> 对象
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('<%s:%s>' % (self.name, self.age))
## 查看内置元类
print(type(People)) # <class 'type'>
print(type(int)) # <class 'type'>
## class关键字定义的类和内置的类都是由type产生的
1. class关键字创建类的步骤
# 类三大特征:类名 class_name || 类的基类 clas_bases = (Object) || 类体本身 --> 一对字符串(执行类体代码,拿到运行空间)
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('<%s:%s>' % (self.name, self.age))
class_body = '''
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('<%s:%s>' % (self.name, self.age))
'''
class_dic = {} # 定义类的命名空间
# 类名
class_name = "People"
# 类的基类
clas_bases = (object,)
# 执行类体代码,拿到运行空间
exec(class_body,{},class_dic) # 空字典指的是全局命名空间 class_dic是类的命名空间
## 运行拿到exec以后可以拿到类体代码的运行空间,放在class_dic 里
print(class_dic)
## {'__init__': <function __init__ at 0x0000016A0BDC9900>, 'say': <function say at 0x0000016A0BE2E320>}
# 调用元类
People = type(class_name,class_basis,class_dic)
print(People) ## <class '__main__.People'>
2. 定制元类,控制类的产生
## 定制元类
class Mymeta(type): ## 只有继承了type类的类才可以称之为元
## 运行__init__方法的时候,空对象和这些class_name,class_basis,class_dic一共四个参数一起传进来了
## 所以需要四个参数接受
## 重写了造对象的方法,不写__new__方法的话自动创建空对象
## 参数为: 类本身,调用类时所传入的参数
def __new__(xls,*args,**kwargs):
##第一种方法 ----------------> 调父类的__new__()方法造对象
return super().__new__(cls,*args,**kwargs)
## 第二种方法 -----------------> 调用元类的内置方法
return type.__new__(cls,*args,**kwargs)
## 可以控制类的产生
def __init__(self,class_name,class_basis,class_dic):
## 类的首字母大写
if not x.capitalize():
raise NameError('类名的首字母必须大写啊!!!!')
class People(object ,metaclass = Mymeta):
# class产生类的话会自动继承object
# 底层的话需要明确之指定继承object类
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('<%s:%s>' % (self.name, self.age))
class_body = '''
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('<%s:%s>' % (self.name, self.age))
'''
class_dic = {} # 定义类的命名空间
# 类名
class_name = "People"
# 类的基类
clas_bases = (object,)
# 执行类体代码,拿到运行空间
exec(class_body,{},class_dic)
# 调用元类
People = Mymeta(class_name,class_basis,class_dic) ## 调用 type.__call__(方法)
## 将参数先传给 __new__方法,造空对象
## 然后参数传递给 __init__方法初始化类
## 调用Mymeta发生的事儿,调用Mymeta 就是type.__call__()
# 先造一个空对象 ==> People 调用__new__方法
# 调用Mymeta这个类的__inti__方法,完成初始化对象的操作(这个过程中可以控制类的产生)
# 返回初始化好的对象
## 总结
# 控制造空对象过程 重写 __new__()方法
# 控制类的产生 重写 __init__()方法
3. new(方法)
## 具体看 2 控制造空对象的过程
## __new__() 放下造对象时,早于 __init__() 方法运行
4. call(方法)
## 1 中
# 调用元类时
People = Mymeta(class_name,class_basis,class_dic) ## 本质就是调用 type的__call__()方法
class Foo:
def __init__(self,x,y):
self.x = x
self.y = y
def __call__(self,name,age):
print(name,age)
print('我运行了obj下面的__call__方法')
obj = Foo(111,222)
obj("yanchen",'18')
# 'yanchen' 18
# '我运行了obj下面的__call__方法'
## 对象的类里定义__call__方法的话,实例对象可以调用
### -------------------------------------------------------------------
## 如果想要控制类的调用, 那就重写__call__()方法
## 定制元类
class Mymeta(type):
def __call__(self,*args,**kwargs):
## Mymeta.__call__函数内会调用People.__new__()方法
people_obj = self__new__(self)
## 可以对类进行定制化
obj.__dict__['xxxx'] ='所有的obj产生的类我新加了一个属性'
## Mymeta.__call__函数内调用People.__inti__()方法
self.__init__(people_obj,*args,**kwargs)
## 重写了造对象的方法,不写__new__方法的话自动创建空对象
## 参数为: 类本身,调用类时所传入的参数
def __new__(xls,*args,**kwargs):
##第一种方法 ----------------> 调父类的__new__()方法造对象
return super().__new__(cls,*args,**kwargs)
## 第二种方法 -----------------> 调用元类的内置方法
return type.__new__(cls,*args,**kwargs)
## 可以控制类的产生
def __init__(self,class_name,class_basis,class_dic):
## 类的首字母大写
if not x.capitalize():
raise NameError('类名的首字母必须大写啊!!!!')
class People(object ,metaclass = Mymeta):
# class产生类的话会自动继承object
# 底层的话需要明确之指定继承object类
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls,*args,**kwargs):
# 造对象
return object.__new__(cls,*args,**kwargs)
def say(self):
print('<%s:%s>' % (self.name, self.age))
## ------------------------------------------------------------
class_body = '''
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print('<%s:%s>' % (self.name, self.age))
'''
class_dic = {} # 定义类的命名空间
class_name = "People"
clas_bases = (object,)
exec(class_body,{},class_dic)
People = Mymeta(class_name,class_basis,class_dic) ## 调用 type.__call__(方法)
## 调用Mymeta发生的事儿,调用Mymeta 就是type.__call__()
# 先造一个空对象 ==> People 调用__new__方法
# 调用Mymeta这个类的__inti__方法,完成初始化对象的操作(这个过程中可以控制类的产生)
# 返回初始化好的对象
obj = People('yanchen',18)
# 实例化People发生的三件事
# 调用Mymeta.__call__(self,*args,**kwargs)方法
# Mymeta.__call__函数内会调用People.__new__()方法
# Mymeta.__call__函数内调用People.__inti__()方法
5. 属性查找的原则

## 属性查找的原则:对象 ----> 类 ----------->父类
## 切记:父类不是元类,不会去从元类里找
No Comments