• 元类


    1.什么是元类

    在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类,即元类可以简称为类的类

    type是内置的一个元类,所有的类都是由type实例化得到,type类是产生所有类的元类

    # 先class 一个类
    class Person:
        def __init__(self,name):
            self.name = name
    
    # 用刚才的类实例化一个对象
    forever = Person('forever')
    
    # 打印一下这个实例化对象的类型
    print(type(forever))  # <class '__main__.Person'>
    print(type(Person))   # <class 'type'>

    运行结果:

    <class 'main.Person'>
    <class 'type'>

    一切皆对象,对象也可以是类,从我们这打印的结果可以看出来,Person的元类就是type

    2.Class底层原理实现

    • 创建类的3个要素:类名,基类,类的名称空间
    • People = type(类名,基类,类的名称空间)

    • type(object_or_name, bases, dict)
    • 通过type来直接产生类,不用class关键字了

    代码:

    dic = {}
    exec(
    '''
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def ku(self):
        print('forever kukudi')   
    ''',{},dic
    )
    # 定义一个类
    Forever = type('Forever',(object,),dic)
    # 实例化一个对象
    forever = Forever('forever',18)
    # 取出类中的值
    print(f'''forever`s name:{forever.name} forever`s age :{forever.age}''')
    # 打印类的父类
    print(Forever.__bases__)

    运行结果:

    forever`s name:forever forever`s age :18
    (<class 'object'>,)

    3.自定义元类控制类的产生

    可以控制类名,可以控制类的继承父类,控制类的名称空间

    自定义元类必须继承type,写一个类继承type 这种类都叫元类

    代码如下:

    class MyClass(type):
        def __init__(self,name,bases,dic):
            print(name)
            #练习一:加限制 控制类名必须以sb开头
             if not name.startswith('sb'):
    raise Exception('类名没有以sb开头')
    练习二:类必须加注释
    print(self.__dict__['__doc__'])

    class MyDemo(object,metaclass=MyClass): def __init__(self,name): self.name = name

    输出结果:

    MyDemo
    报错信息:
    raise Exception('类名中没有name字段')
    Exception: 类名中没有name字段

    不报错的定义代码:

    class Name(object,metaclass=MyClass):
        def __init__(self,name):
            self.name = name

    运行结果:

    Name

    4.自定义元类控制类的执行过程

    __call__

    控制类的调用过程,实际上在控制:对象的产生

    程序代码:

    class MyClass(type):
        def __call__(self, *args, **kwargs):
            obj=object.__new__(self)
            obj.__init__(*args, **kwargs)
    
            obj.__dict__={ '_%s__%s'%(self.__name__,k):v for k,v in obj.__dict__.items()}
    
            return obj
    
    class MyDemo(object, metaclass=MyClass):
        def __init__(self, name):
            self.name = name
    
    demo = MyDemo(name='forever')
    print(demo.__dict__)
    print(demo.name)
    print(demo._MyDemo__name)

    运行结果:

    print(demo._MyDemo__name)

    {'_MyDemo__name': 'forever'}
    forever

    print(demo.name)

    Traceback (most recent call last):
    {'_MyDemo__name': 'forever'}
    File "F:/shpython11/pycharmwork/first_project/study_start/day29/homework.py", line 75, in 
    print(demo.name)
    AttributeError: 'MyDemo' object has no attribute 'name'

    5.属性查找

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

    程序代码:

    class Mymeta(type):
        n=444
    
        def __call__(self, *args, **kwargs): #self=<class '__main__.OldboyTeacher'>
            obj=self.__new__(self)
            # print(self.__new__ is object.__new__) #True
            obj.__init__(*args, **kwargs)
            return obj
    
    
    class Bar(object):
        # n=333
        pass
    
        # def __new__(cls, *args, **kwargs):
        #     print('Bar.__new__')
    
    class Foo(Bar):
        # n=222
        pass
    
        # def __new__(cls, *args, **kwargs):
        #     print('Foo.__new__')
    
    class OldboyTeacher(Foo,metaclass=Mymeta):
        # n=111
    
        school='oldboy'
    
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def say(self):
            print('%s says welcome to the oldboy to learn Python' %self.name)
    
    
        # def __new__(cls, *args, **kwargs):
        #     print('OldboyTeacher.__new__')
    
    
    o=OldboyTeacher('forever',18) #触发OldboyTeacher的类中的__call__方法的执行,进而执行self.__new__开始查找
    print(OldboyTeacher.n)

    1.什么是元类

    在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类,即元类可以简称为类的类

    type是内置的一个元类,所有的类都是由type实例化得到,type类是产生所有类的元类

    # 先class 一个类
    class Person:
        def __init__(self,name):
            self.name = name
    
    # 用刚才的类实例化一个对象
    forever = Person('forever')
    
    # 打印一下这个实例化对象的类型
    print(type(forever))  # <class '__main__.Person'>
    print(type(Person))   # <class 'type'>

    运行结果:

    <class 'main.Person'>
    <class 'type'>

    一切皆对象,对象也可以是类,从我们这打印的结果可以看出来,Person的元类就是type

    2.Class底层原理实现

    • 创建类的3个要素:类名,基类,类的名称空间
    • People = type(类名,基类,类的名称空间)

    • type(object_or_name, bases, dict)
    • 通过type来直接产生类,不用class关键字了

    代码:

    dic = {}
    exec(
    '''
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def ku(self):
        print('forever kukudi')   
    ''',{},dic
    )
    # 定义一个类
    Forever = type('Forever',(object,),dic)
    # 实例化一个对象
    forever = Forever('forever',18)
    # 取出类中的值
    print(f'''forever`s name:{forever.name} forever`s age :{forever.age}''')
    # 打印类的父类
    print(Forever.__bases__)

    运行结果:

    forever`s name:forever forever`s age :18
    (<class 'object'>,)

    3.自定义元类控制类的产生

    可以控制类名,可以控制类的继承父类,控制类的名称空间

    自定义元类必须继承type,写一个类继承type 这种类都叫元类

    代码如下:

    class MyClass(type):
        def __init__(self,name,bases,dic):
            print(name)
            if 'name' not in name.lower():
                raise Exception('类名中没有name字段')
    
    class MyDemo(object,metaclass=MyClass):
        def __init__(self,name):
            self.name = name

    输出结果:

    MyDemo
    报错信息:
    raise Exception('类名中没有name字段')
    Exception: 类名中没有name字段

    不报错的定义代码:

    class Name(object,metaclass=MyClass):
        def __init__(self,name):
            self.name = name

    运行结果:

    Name

    4.自定义元类控制类的执行过程

    __call__

    控制类的调用过程,实际上在控制:对象的产生

    程序代码:

    class MyClass(type):
        def __call__(self, *args, **kwargs):
            obj=object.__new__(self)
            obj.__init__(*args, **kwargs)
    
            obj.__dict__={ '_%s__%s'%(self.__name__,k):v for k,v in obj.__dict__.items()}
    
            return obj
    
    class MyDemo(object, metaclass=MyClass):
        def __init__(self, name):
            self.name = name
    
    demo = MyDemo(name='forever')
    print(demo.__dict__)
    print(demo.name)
    print(demo._MyDemo__name)

    运行结果:

    print(demo._MyDemo__name)

    {'_MyDemo__name': 'forever'}
    forever

    print(demo.name)

    Traceback (most recent call last):
    {'_MyDemo__name': 'forever'}
    File "F:/shpython11/pycharmwork/first_project/study_start/day29/homework.py", line 75, in 
    print(demo.name)
    AttributeError: 'MyDemo' object has no attribute 'name'

    5.属性查找

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

    程序代码:

    class Mymeta(type):
        n=444
    
        def __call__(self, *args, **kwargs): #self=<class '__main__.OldboyTeacher'>
            obj=self.__new__(self)
            # print(self.__new__ is object.__new__) #True
            obj.__init__(*args, **kwargs)
            return obj
    
    
    class Bar(object):
        # n=333
        pass
    
        # def __new__(cls, *args, **kwargs):
        #     print('Bar.__new__')
    
    class Foo(Bar):
        # n=222
        pass
    
        # def __new__(cls, *args, **kwargs):
        #     print('Foo.__new__')
    
    class OldboyTeacher(Foo,metaclass=Mymeta):
        # n=111
    
        school='oldboy'
    
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def say(self):
            print('%s says welcome to the oldboy to learn Python' %self.name)
    
    
        # def __new__(cls, *args, **kwargs):
        #     print('OldboyTeacher.__new__')
    
    
    o=OldboyTeacher('forever',18) #触发OldboyTeacher的类中的__call__方法的执行,进而执行self.__new__开始查找
    print(OldboyTeacher.n)
  • 相关阅读:
    网页鼠标点击特效
    ElementUI 删除 el-table 当前选中行(不是selection列)
    Vue阻止冒泡
    Vue实现选项卡切换
    Vue的条件渲染
    Vue实现勾选后向数组都添加
    Vue实现商城里面多个商品计算,全选,删除
    VUE实现请求数据
    JS实现数组每次只显示5条数据
    移动端分享到微信和QQ
  • 原文地址:https://www.cnblogs.com/whnbky/p/11455464.html
Copyright © 2020-2023  润新知