元类
在python中一切皆对象,name我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类,即元类可以简称为类的类
元类是负责产生类的,所以我们学习元类或者定义元类的目的是:为了控制类的产生过程,还可以控制对象的产生过程
类的组成
class People(object):
x = 1
print('from people')
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print('from speak')
在用class关键字定义类时,在定义阶段会执行类体中的代码,创建名称空间,所以类由三部分组成
- 类名class_name:People
- 基类class_bases:(object,)
- 类的名称空间class_dic
内置函数 exec()
将字符串中的代码执行,然后把产生的全局名称丢入到global_space字典中,局部名称丢入到local_space字典中
cmd = """
x = 1
global y
y = 10
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print('from speak')
"""
global_space = {}
local_space = {}
exec(cmd,global_space,local_space) # 未声明gloabal的变量全是局部变量
print('local:',local_space)
local: {'x': 1, '__init__': <function __init__ at 0x000002C2319EB158>, 'speak': <function speak at 0x000002C2319EB0D0>}
class关键字创建类原理
用class关键字创建一个类,用的默认的元类type
class_name = 'P' # 类名
class_bases = (object,) # 基类
cmd = """
x = 1
global y
y = 10
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print('from speak')
"""
global_space = {}
local_space = {}
exec(cmd,global_space,local_space)
class_dic = local_space # 类的名称空间
P= type(class_name, class_bases, class_dic)
print(P)
<class '__main__.P'>
自定义元类控制类的创建
- 控制创建类时必须写说明,没写就抛出异常
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dict):
if not class_dict.get('__doc__'):
raise TypeError('必须写说明')
super(Mymeta, self).__init__(class_name, class_bases, class_dict)
class People(object, metaclass=Mymeta):
"""
SJFDSFSD
"""
country = 'Chinese'
def __init__(self, name, age):
self.name = name
self.age = age
def test(self):
print('from f1')
- 控制创建类时类名不能全为小写,类名全为小写则抛出异常
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dict):
if class_name.islower():
raise TypeError('类名不能全为小写')
super(Mymeta, self).__init__(class_name, class_bases, class_dict)
class People(object, metaclass=Mymeta):
country = 'Chinese'
def __init__(self, name, age):
self.name = name
self.age = age
def test(self):
print('from f1')
自定义元类控制类实例化
类的实例化就是元类的调用,类实例化原理:
- 先造出一个空对象
- 为该空对象初始化独有的属性
- 返回一个初始化好的对象
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dict):
super(Mymeta, self).__init__(class_name, class_bases, class_dict)
# 控制类Foo的调用过程,即控制实例化Foo的过程
def __call__(self, *args, **kwargs):
# 造一个空对象obj
obj = object.__new__(self)
# 调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
self.__init__(obj, *args, **kwargs)
return obj
class Foo(object, metaclass=Mymeta):
x = 10
def __init__(self, y):
self.y = y
f = Foo(1)
print(f.__dict__)
{'y': 1}
自定义元类后对象属性查找顺序
对象本身-->类-->父类-->父类-->object-->type找不到报错