我们class定义一个类,实例化产生对象:
class People:
pass
p1 = People()
# python 一切皆对象,p1是People实例化的,那People这个类也是对象,People是哪个类产生的?
print(type(p1))
# <class '__main__.People'>
print(type(People))
# <class 'type'>
type函数可以用来看产生对象的类,可以看到我们class定义的类默认是type这个类实例化的对象
产生类的两种方式
class定义类
class Chinese:
def __init__(self, name, age):
self.name = name
self.age = age
def talk(self):
print('talking')
# print(Chinese)
# <class '__main__.Chinese'>
调用元类type产生
class_name = 'Chinese' # 类名
class_bases = (object,) # 继承父类
class_body = '''
country = 'china'
def __init__(self, name, age):
self.name = name
self.age = age
def talk(self):
print('talking')
''' # 类的内容
class_dict = {}
exec(class_body,globals(),class_dict) # 为类产生局部名称空间
# print(class_dict)
# {'country': 'china', '__init__': <function __init__ at 0x000001ABF45FC1E0>, 'talk': <function talk at 0x000001ABF65D8BF8>}
C = type(class_name,class_bases,class_dict) # 调用type产生类
# print(C)
# <class '__main__.Chinese'>
自定义元类
自定义元类控制类的创建
自定义元类其实就是创建一个继承元类type 的类,以此作为元类实例化创建类。
之前我们看到调用type元类传入了三个参数,
C = type(class_name,class_bases,class_dict)
那我们自定义元类之后也要传入这三个参数,不用管内部怎么处理,继承元类type的功能就行。我们可以添加条件控制以此为元类创建的类的行为。
# C = type(class_name,class_bases,class_dict)
# 创建一个继承元类type的类
class Test(type): # 继承元类type的属性
def __init__(self, class_name, class_bases, class_dict):
if not class_name.istitle(): # 加入条件
raise TypeError('首字母大写')
super(Test, self).__init__(class_name, class_bases, class_dict)
class Chinese(metaclass=Test):
def __init__(self, name,age):
self.name = name
self.age = age
def talk(self):
print('talking')
print(Chinese)
# <class '__main__.Chinese'>
class people(metaclass=Test):
pass
print(people)
# TypeError: 首字母大写
或者直接调用type__new__方法:
class Test(type): # 继承元类type的属性
def __new__(cls, *args, **kwargs):
return type.__new__(cls,*args,**kwargs)
class Chinese(metaclass=Test):
def __init__(self, name,age):
self.name = name
self.age = age
def talk(self):
print('talking')
# print(Chinese)
# <class '__main__.Chinese'>
自定义元类控制类的实例化
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print(self,args,kwargs)
p1 = People('小明', 18)
p1('a','b',num='18')
# <__main__.People object at 0x000001DD97AD9208> ('a', 'b')
如果我们定义一个类,类中有__call__方法,那实例化产生的对象可以调用 p1(‘a’,‘b’,num=‘18’),
同样的,反之推导,如果我们把类People看作是元类产生的对象,既然我们可以调用People(‘小明’, 18)那么元类中应该有__call__方法,既然如此,我们可以看作调用People(‘小明’, 18)实例化产生的对象p1就可以看作是元类中调用__call__方法的返回值
class Test(type):
def __init__(self, class_name, class_bases, class_dict):
super(Test,self).__init__(class_name, class_bases, class_dict)
def __call__(self, *args, **kwargs): # 实例化时的属性值,self = People,参数:'小明',18
obj = object.__new__(self) # 产生空对象obj
self.__init__(obj, *args, **kwargs) # self= People, 转到People.__init__(self, name, age):
return obj # 返回obj
class People(object, metaclass=Test):
def __init__(self, name, age):
self.name = name
self.age = age
def run(self):
print('running')
p1 = People('小明',18)
示例
比如要求实例化时参数必须用关键字形式,自定义产生的属性必须大写:
class Test(type):
def __new__(cls, *args, **kwargs):
return type.__new__(cls, *args, **kwargs)
def __call__(self, *args, **kwargs):
if args:
raise TypeError
obj = object.__new__(self)
for k,v in kwargs.items():
obj.__dict__[k.upper()]=v
return obj
class People(metaclass=Test):
def talk(self):
print('talking')
p1 = People(name='小明')
# print(p1.__dict__)
# {'NAME': '小明'}