贰拾叁

一、元类

​ 在python中一切皆对象,所以类也是一个对象,对象是由类实例化产生的,所以类也可以实例化产生。那么实例化产生类的类就是元类。

class B
	def __init__(self,v)
print(type(B))

<class 'type'>

​ 使用print(type(类))的方法可以找到类的类。

​ type为python内置元类,所有的类都是由type实例化产生的。

二、class底层原理分析

​ 平时使用class + 类名的方式将类构造出来,但实际上这些类是由元类实例化产生的。type为python内置元类,类是由type实例化产生,并且传入一堆参数。

​ type是使用类的内置__init__方法产生类的。

    # 类的源码
    def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
        """
        type(object_or_name, bases, dict)
        type(object) -> the object's type
        type(name, bases, dict) -> a new type
        # (copied from class doc)
        """
        pass

​ 元类通过object_or_name, bases, dict(类名:字符串,父类,名称空间:字典)的方式产生类,可以代替class关键字的方式。

#通过type来直接产生类,不用class关键字了
l={}
exec('''
school='oldboy'
def __init__(self,name):
    self.name=name
def score(self):
    print('分数是100')
''',{},l)
def __init__(self,name):
    self.name=name

# Person=type('Person',(object,),{'school':'oldboy','__init__':__init__})
#
Person=type('Person',(object,),l)

三、通过元类控制类的产生

​ 通过控制类名,控制类的继承父类,控制类的名称空间的方法自定义元类,由此可以控制类的产生。

​ 自定义元类,都要继承type元类。

class A(type):

class B(metaclass=  A):

​ metaclass= A指定类B的元类为A。

​ 练习:自定义元类,控制类产生,类的名称空间必须要有name字段才能创建成功,否则失败。

lass Mymeta(type):
    def __init__(self,name):
        if not 'name' in name:
            raise   TypeError('没有name字段')

class Aname(object,metaclass=Mymeta):
    def __init__(self,name):
        self.name = name

四、通过元类控制类的调用

​ 通过元类控制类的调用实际上是在控制对象的产生。

class Mymeta(type):
    def __call__(self, *args, **kwargs):
        # print('xxx')

        return 1

class Person(object,metaclass=Mymeta):
    school='oldboy'
    def __init__(self,name):
        self.name=name
    def score(self):
        print('分数是100')

p=Person('nick')
print(p.name)

​ 类的调用过程是先触发元类的__call__ ,再触发类的init方法。

​ 练习:定义一个元类,定义一个类继承字典,使其具备点取值和赋值功能,通过元类控制对象的产生,把所有属性放在attr字典中,属性全删除。

class Mymeta(type):
    def __call__(self, *args, **kwargs):
        obj = self.__new__(self)
        obj.__init__(*args, **kwargs)
        dic = {}
        dict.update(obj.__dict__)
        attr = {'attr':dic}
        obj.__dict__.clear()
        obj.__dict__.update(attr)
        

class Test(dict,metaclass=Mymeta):
    def __init__(self,**kwargs):
        self.__dict__.update(kwargs)
    def __getattr__(self, item):
        return self.__dict__['attr'][item]
    def __setattr__(self, key, value):
        self.__dict__['attr'][key] = value
        t = Test(name='lqz', age=18)
print(t.__dict__)
print(t.name)
print(t.age)
t.male = 'nan'
print(t.male)
print(t.__dict__)

五、有元类后属性查找顺序

​ 类的属性查找顺序:先从类本身中找--->mro继承关系去父类中找---->去自己定义的元类中找--->type中--->报错

​ 对象的属性查找顺序:先从对象自身找--->类中找--->mro继承关系去父类中找--->报错

5f192fd059540a603a133d3ff0b0ca0

posted @ 2019-09-03 21:30  唐ceng  阅读(283)  评论(0编辑  收藏  举报