• 元类的使用


    导读:

    在Python里一切都是对象(object),基本数据类型,如数字,字符串,函数都是对象。对象可以由类(class)进行创建。那么既然一切都是对象,那么类是对象吗?

    是的,类也是对象,那么又是谁创造了类呢?答案也很简单,也是类,一个能创作类的类,称之为元类(type)

    1. 类的定义

    对象是通过类创建的,如下面的代码:

    # object 为顶层基类
    class Work(object):
        a = 100
    
    Mywork = Work()   # 实例化
    print(Mywork )   # Mywork 是 Work 所创建的一个对象  <__main__.Work object at 0x101eb4630>
    print(type(Mywork))    # <class '__main__.Work'>
    print(type(Work))    # 类型为元类 <class 'type'>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    解析:

    • 可以看见对象 Mywork 是类 Work 创建的实例。然但是可以看到Work的类型时由一个叫 type 的类创建的实例。即 Mywork —》 Work —》 type 创建

    • 上面的例子中对象是动态创建的,类则是通过关键字 class 声明定义的

    • 那么class关键字背后的玄机是什么呢?

      • 实际上,class Work(object) 这样的代码,等价于 Work = type(‘Work’, (objects, ), {“a”:100})
      • 即类 type 通过实例化创建了它的对象 Work,而这个 Work 恰恰是一个类,这样能创建类的类,就是 Python 的元类。而在python中内置的元类叫:type

    一、什么是元类

    • 用来创建类的类,叫做元类
    • 类是元类创建出来的对象
    • 函数type实际上是一个元类,type就是Python在背后用来创建所有类的元类

    二、注意区分元类和继承的基类

    • type是元类,所有的类都是通过type所创建出来的
    • object顶层的基类,所有类的继承顶层父类都是object

    三、type 元类的使用

    1. 可以看到type是小写,一般情况下都会认为它是一个函数,通过查看源代码去看下如下定义的:

      class type(object):
      """
      type(object_or_name, bases, dict)
      type(object) -> the object's type
      type(name, bases, dict) -> a new type
      """
      	# 实例化
      	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
      	     
      	# 创建类    
      	@staticmethod     # known case of __new__
          def __new__(*args, **kwargs):   # real signature unknown
              """ 
              Create and return a new object.  See help(type) for accurate signature. 
              (创建并返回一个新对象)
              """
              pass
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    2. type的用法一:获取数据时那种类型 : type(object) -> the object’s type

      a = 100
      b = "100"
      c = [11,22,33]
      
      print(type(a))    # ======》 <class 'int'>
      print(type(b))    # ======》 <class 'str'>
      print(type(c))    # ======》 <class 'list'>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    3. type的用法二:创建类:type(object_or_name, bases, dict)

      1.在查看源码的时候,可以看到在初始化时,init__方法接受三个参数,type 在实例化的过程,也会重新创建一个新的类,而创建类的代码来自__new 方法,它的参数与 __init__方法是一样的。

      2.当调用 type 进行实例化的时候,会先自动调用 new 方法,再调用__init__方法,最终会实例化一个对象,这个对象是一个类。

      1. 元类 type 的 init 方法有3个参数:
       1.name:类名(字符串类型)
       2.bases:继承的父类(元祖类型)
       3.dict:属性和方法组成的字典(字典类型)
      
      • 1
      • 2
      • 3

      具体例子:

      # 通过 class 定义类
      class Myclass(object):
          a = 100
          b = 200
      
      
      # 通过type创建的类(动态创建类)
      Myclass1 = type("Myclass1",(object,),{"a":"100","b":"200"})
      
      print(Myclass)
      print(Myclass1)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      在这里插入图片描述

      如果需要定义实例方法和类属性怎么办呢?,将方法和属性以字典的形式传进去

      def work(self):
          print("这是实例方法——————work————————")
      
      # 定义类属性值
      def init_method(self, aa, bb, cc):
          self.aa = aa
          self.bb = bb
          self.cc = cc
      		
      # 通过type创建的类(动态创建类)
      Myclass2 = type("Myclass2",(object,),{"a":"100","b":"200","work":work,"work_1":work_1,"__init__":init_method})
      
      m = Myclass2(11,22,33)
      m.work()
      print(m.aa, m.bb, m.cc)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      在这里插入图片描述

    四、自定义元类的使用

    1. 既然元类可以创建类,那也可以自定义元类,自定义直接继承类 type ,在自定义元类的步骤:

      1.定义一个类继承type
      2.重写new方法

      具体例子:

      # 定义一个类继承type
      class Mytest(type):
      
      	# 重写new方法
          def __new__(cls, type_name, bases, atter, *args, **kwargs):
              new_cls = super().__new__(cls,type_name, bases, atter)         
              return new_cls      # 返回新的类
      
      M2 = Mytest("M2",(Mytest,),{"atter":100})
      print(M2)     # =====》  <class '__main__.M2'>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    2. 使用class创建类的时候指定自定义的元类

      1.不去指定时,默认创建都是type类
      2.指定自定义的元类去创建类:metaclass = 指定的元类

      class Myclass(type):
          """自定义的元类"""
      
          def __new__(cls, type_name, bases, attrs, *args, **kwargs):
              new_cls = super().__new__(cls, type_name, bases, attrs)
              print("这个是Myclass:", type_name, bases, attrs, )
              return new_cls
      
      # 通过metaclass=xxxx   继承自定义元类
      class Inherited_class(metaclass=Myclass):
          a = 100
          b = 200
      
      
      print(type(Inherited_class))  # ======》 <class '__main__.Myclass'>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      在这里插入图片描述

  • 相关阅读:
    考前冲刺上岸浙工商MBA的备考经验分享
    python脚本-网页爬虫获取网页图片
    如何使用Python进行Web开发,如Flask或Django?
    Vue路由组件的缓存keep-alive和include属性
    基于SSM的人事管理系统
    opengles 绘制图元 ——glDrawArrays() 相关API介绍 (十)
    软件测试——从0开始的ios自动化测试(一)
    阿里云服务器系统怎么选?Alibaba Cloud Linux操作系统介绍
    1.java环境搭建与eclipse安装和配置
    单例模式、工厂模式 c++关键字 static
  • 原文地址:https://blog.csdn.net/qq_40236497/article/details/125422104