python-元类
python中一切皆对象,类的实例是对象,实例的类型是类,类的类型是元类(type)。
class关键字定义的类本身也是一个对象,负责产生该对象的类称为元类,内置的元类为type。
除了用class定义类,也可以用type动态的创建类,传递类名、基类、类的名称空间即可创建一个类。
class A:
pass
print(type(A), type(A())) # <class 'type'> <class '__main__.A'>
B = type('B', (), {'x':1})
b = B()
print(b.x)
def fun(self):
print(self.name)
# 类名:str, 基类:tuple, 名称空间:dict
C = type('B', (A,), {'name':'C', 'fun':fun})
print(C.name)
c = C()
c.fun()
自定义元类
默认情况下所有类的元类是type,可以基础type自定义元类
class Mymeta(type):
def __init__(self, class_name, class_basses, class_dic):
super(Mymeta, self).__init__(class_name, class_basses, class_dic)
if not class_name.istitle():
raise TypeError("类名首字母要大写")
if '__doc__' not in class_dic or len(class_dic['__doc__'].strip())==0:
raise TypeError("类中要有注释")
try:
class A(metaclass=Mymeta):
pass
except Exception as e:
print(e) # 类中要有注释
try:
class b(metaclass=Mymeta):
pass
except Exception as e:
print(e) # 类名首字母要大写
__new__
创建对象时,首先调用new方法创建一个空对象并返回,然后指向init方法进行初始化,new是一个类方法
class Mymeta(type):
def __init__(self, class_name, class_basses, class_dic):
super(Mymeta, self).__init__(class_name, class_basses, class_dic)
def __new__(cls, *args, **kwargs):
print("__new__")
print(cls)
print(args)
print(kwargs)
return super().__new__(cls, *args, **kwargs)
class A(metaclass=Mymeta):
pass
a = A()
# __new__
# <class '__main__.Mymeta'>
# ('A', (), {'__module__': '__main__', '__qualname__': 'A'})
# {}
__call__方法
如果类中定义了call方法,那么类的对象就是一个callable对象。
类是元类的对象,那么在创建类的对象时会调用元类的call方法。
class Mymeta(type):
def __init__(self, class_name, class_basses, class_dic):
print("__init__")
super(Mymeta, self).__init__(class_name, class_basses, class_dic)
def __new__(cls, *args, **kwargs):
print("__new__")
print(cls)
print(args)
print(kwargs)
return super().__new__(cls, *args, **kwargs)
def __call__(self, *args, **kwds):
print("__call__")
print(self)
return super().__call__(*args, **kwds)
class A(metaclass=Mymeta):
pass
print('create a object')
a = A()
"""
__new__
<class '__main__.Mymeta'>
('A', (), {'__module__': '__main__', '__qualname__': 'A'})
{}
__init__
create a object
__call__
<class '__main__.A'>
"""
在定义类的时候就会调用元类的__new和__init方法,而对象的产生是调用元类的__call__方法