元类
元类的用途:自定义元类控制类的创建行为及类的实例化行为
Python 中一切皆为对象。
一切接对象,对象可以怎么用呢?
1、都可以被引用,x=obj
2、都可以当作函数的参数传入
3、都可以当作函数的返回值
4、都可以当作容器类的元素,l=[func,time,obj,1]
让我们先定义一个类,然后逐步分析
class People(): def __init__(self, name, age): self.name = name self.age = age def say(self): print('%s say welcome to here' % self.name) p = People('ysg', 21) p.say() print(type(p)) # <class '__main__.People'> print(type(People)) # <class 'type'>
所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化),比如对象t1是调用类OldboyTeacher得到的
如果一切皆为对象,那么类 Peope 本质也是一个对象,既然所有的对象都是调用类得到的,那么 Peope 必然也是调用了一个类得到的,这个类称为元类
总结:产生类的类称之为元类,默认使用 class 定义的类,他们的元类是 type。
exec的用法
参数1:字符串形式的命令
参数2:全局作用域(字典形式),如果不指定默认就是用 globals()
参数3:局部作用局(字典形式),如果不指定默认就是用 locals()
例子
g = { 'x': 'ysg', 'y': '123' } l = {} exec(""" global x,m x = 'ysging' m = 'pei' z = '21' """, g, l) print(g) # {'x': 'ysging', 'y': '123'..., 'm': 'pei'} print(l) # {'z': '21'}
元类定义的两种方式
方法一:class
class People(): country = "China" def __init__(self, name, age): self.name = name self.age = age def func(self): print('%s say good' % self.name) p = People('ysg', '22') print(People) # <class '__main__.People'> print(p, p.name, p.age) # <__main__.People object at 0x0000020B0FC652E8> ysg 22
方法二:type
定义类的三要素:类名、类的基类、类的名称空间
class_name = 'People' class_bases = (object,) class_body = """ country = "China" def __init__(self, name, age): self.name = name self.age = age def func(self): print('%s say good' % self.name) """ class_dic = {} exec(class_body, globals(), class_dic) People1 = type(class_name, class_bases, class_dic) print(People1) # <class '__main__.People'> p1 = People1('ysg', '22') print(p1, p1.name, p1.age) # <__main__.People object at 0x0000020B0FC65470> ysg 22
自定义元类控制类的创建行为
实现检索类名称是否为大写,类中是否写入注释
class Mymeta(type): def __init__(self, class_name, class_bases, class_dic): super(Mymeta, self).__init__(class_name, class_bases, class_dic) if not class_name.istitle(): raise TypeError('类名称首字母要求大写') if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError('新建的类必须标有注释') class People(object, metaclass=Mymeta): # People = Mymeta(class_name,class_bases,class_dic) ''' 使用自定义元类控制类的创建行为 ''' country = "China" def __init__(self, name, age): self.name = name self.age = age def func(self): print('%s say good' % self.name)
自定义元类控制类的实例化行为
预备知识 __call__
class Foo(): pass f = Foo() f() # TypeError: 'Foo' object is not callable
class Foo(): def __call__(self, *args, **kwargs): print(self) print(args) print(kwargs) f = Foo() f(1, 2, 3, a=1, b=2, c=3) 结果: <__main__.Foo object at 0x000001DBE6B7F240> (1, 2, 3) {'a': 1, 'b': 2, 'c': 3}
由以上两个例子可以看出,在调用方式实际是自动调用了 __call__ 方法
所以可以得出,在使用元类控制类的实例化行为时:
元类内部也应该有一个 __call__ 方法,会在调用 Foo 时触发执行;Foo(1,2,x=1) 就相当于 Foo.__call__(Foo,1,2,x=1)