zoukankan      html  css  js  c++  java
  • 元类 metaclass

    二、元类metaclass

    实例对象是由类来创建,那么类又是由什么来创建的呢? 答案就是元类

    1.类的类型:是元类

    元类创建类,类创建对象。

    # 元类
    print(type(1))  # <class 'int'>
    print(type(int))  # <class 'type'>

    2.理解python中的类也是对象

    Python中类的概念借鉴于Smalltalk,这显得有些奇特。在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段。在Python中这一点仍然成立。

    class ObjectCreator(object):
        pass
    
    my_object = ObjectCreator()
    print my_object
    #输出:<__main__.ObjectCreator object at 0x8974f2c>

     类同样也是一种对象。只要你使用关键字class,Python解释器在执行的时候就会创建一个对象。下面的代码段:

    class ObjectCreator(object):
         pass

    将在内存中创建一个对象,名字就是ObjectCreator。这个对象(类)自身拥有创建对象(类实例)的能力,而这就是为什么它是一个类的原因。但是,它的本质仍然是一个对象,于是你可以对它做如下的操作:
    你可以将它赋值给一个变量,

    你可以拷贝它,

    你可以为它增加属性,

    你可以将它作为函数参数进行传递。

    3.type创建元类--------所有的类都是type创建的对象:原理

    # 元类
    print(type(1))  # <class 'int'>
    print(type(int))  # <class 'type'>
    print(type(type)) # <class 'type'> 元类的类型就是它自己

    原型:type(类名,基类元组(可以为空,用于继承), 包含属性或函数的字典)

     以下两种写法都可以:

    type('Classname',(object,),dict(hello=fun()))

    type('Classname',(object,),{"hello":fun()})

    1、class 自定义的类名称

    2、(object,)是继承类,的元组,如果只有一个就写这种形势(object,);多个(object,xxxx,)

    3、dict(hello=fun()) 或 {"hello":fun()} 第三个参数,是一个字典等号左是 自定义的方法名,右侧是已写好的方法名,这个要注意,有参数且没有默认值的情况下,要加括号;

    # 如何使用元类创建类
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    
    def sing(self,song):
        print(f"{self.name} is sing {song} !")
    
    
    # 所有类都是type创建的对象
    stu = type("Student", (object,), {     # 当你 class ClassName 底层就是用type实现类的创建过程
        "__init__": __init__,
        "sing": sing
    })
    
    if __name__ == '__main__':
        # 使用类创建对象
        obj = MyClass()
        # 元类创建类
        # stu 相当于接收Student类; stu()实例化类;stu().name方法,调用的其实是我们定义的__ini__()构造方法(fun)。
        print(stu)  # <class '__main__.Student'>
        print(stu("goge", 18)) # <__main__.Student object at 0x00000253C153FE88>
        s = stu("zhangsan", 20)
        print(s.name)  # zhangsan
        print(s.age)  # 20
        print(s.sing("夜曲"))  # zhangsan is sing 夜曲 !

    int,list....等类都是由元类创建的,首字母小写了。

    同理,有非object类的继承,直接继承写在元组里即可(object要删除掉)。object也是由type创建的。是默认的最顶层的类,即强制默认从object继承

    4.实际应用中创建元类:继承type

    # 继承type创建元类
    class MyMetaClass(type):
    
        def func(self):
            print("func is running...")
    
        def __new__(cls, name: str, bases: tuple, attr: dict):
            # __new__创建对象(重写定义了创建对象的过程)
            """
            创建对象(这个对象是一个类)
            :param name: 字符串,类的名称
            :param bases: 元组(基础类1,基础类2,...)
            :param attr: 字典(__dict__属性)
            """
            name = "Person"
            attr["name"] = "zhangsan"
            attr["age"] = 19
            attr["func"] = cls.func
            attr["add"] = lambda self,a,b: a+b
            bases = (object,)
            return type.__new__(cls, name,bases, attr)
    
    # metaclass 指定类是由谁创建的
    # 所有类,如果不指定metaclass,默认metaclass是type
    # 自定义某个元类,通常是从type创建的
    class MyClass(object, metaclass=MyMetaClass): # 不指定metaclass,默认metaclass=type
        pass
    
    if __name__ == '__main__':
        print(MyClass.__bases__)  # (<class 'object'>,)
        print(MyClass.__name__)  # Person
        print(MyClass.__dict__)  #  {'__module__': '__main__', 'name': 'zhangsan', 'age': 19, 'func': <function MyMetaClass.func at 0x000001AAC24663A8>, 'add': <function MyMetaClass.__new__.<locals>.<lambda> at 0x000001AAC24664C8>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
        print(MyClass.func)   #  <function MyMetaClass.func at 0x000001AAC24663A8>
        print(MyClass.add)   # <function MyMetaClass.__new__.<locals>.<lambda> at 0x000001
  • 相关阅读:
    navicat执行大容量的.sql文件时的设置
    unity3d的四元数 Quaternion
    Unity运行时刻资源管理
    unity3d 加密资源并缓存加载
    unity3d webplayer 16:9 居中显示模板
    quaternion*Vector3的新理解
    PoolManager
    网上关于碰撞的资料
    游戏美术:色彩原理
    unity3d下载Obb分包文件
  • 原文地址:https://www.cnblogs.com/ananmy/p/14233218.html
Copyright © 2011-2022 走看看