加入收藏 | 设为首页 | 会员中心 | 我要投稿 财气旺网 - 财气网 (https://www.caiqiwang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

Python MetaClass元类解说

发布时间:2022-11-03 12:44:13 所属栏目:语言 来源:
导读:  MetaClass元类,本质也是一个类,但和普通类的用法不同,它可以对类内部的定义(包括类属性和类方法)进行动态的修改。可以这么说,使用元类的主要目的就是为了实现在创建类时,能够动态地改变类中定义的属性或者
  MetaClass元类,本质也是一个类,但和普通类的用法不同,它可以对类内部的定义(包括类属性和类方法)进行动态的修改。可以这么说,使用元类的主要目的就是为了实现在创建类时,能够动态地改变类中定义的属性或者方法。
  不要从字面上去理解元类的含义,事实上 MetaClass 中的 Meta 这个词根,起源于希腊语词汇 meta,包含“超越”和“改变”的意思。
 
  举个例子,根据实际场景的需要,我们要为多个类添加一个 name 属性和一个 say() 方法。显然有多种方法可以实现,但其中一种方法就是使用 MetaClass 元类。
 
  如果在创建类时,想用 MetaClass 元类动态地修改内部的属性或者方法,则类的创建过程将变得复杂:先创建 MetaClass 元类,然后用元类去创建类,最后使用该类的实例化对象实现功能。
 
  和前面章节创建的类不同,如果想把一个类设计成 MetaClass 元类,其必须符合以下条件:
  必须显式继承自 type 类;
  类中需要定义并实现 __new__() 方法,该方法一定要返回该类的一个实例对象,因为在使用元类创建类时,该 __new__() 方法会自动被执行,用来修改新建的类。
 
  讲了这么多,读者可能对 MetaClass 元类的功能还是比较懵懂。没关系,我们先尝试定义一个 MetaClass 元类:
  #定义一个元类
  class FirstMetaClass(type):
      # cls代表动态修改的类
      # name代表动态修改的类名
      # bases代表被动态修改的类的所有父类
      # attr代表被动态修改的类的所有属性、方法组成的字典
      def __new__(cls, name, bases, attrs):
          # 动态为该类添加一个name属性
          attrs['name'] = "C语言中文网"
          attrs['say'] = lambda self: print("调用 say() 实例方法")
          return super().__new__(cls,name,bases,attrs)
  此程序中,首先可以断定 FirstMetaClass 是一个类。其次,由于该类继承自 type 类,并且内部实现了 __new__() 方法,因此可以断定 FirstMetaCLass 是一个元类。
  有关 __new__() 的具体用法,可阅读《Python __new__()方法》一节。
 
  可以看到,在这个元类的 __new__() 方法中,手动添加了一个 name 属性和 say() 方法。这意味着,通过 FirstMetaClass 元类创建的类,会额外添加 name 属性和 say() 方法。通过如下代码,可以验证这个结论:
  #定义类时,指定元类
  class CLanguage(object,metaclass=FirstMetaClass):
      pass
  clangs = CLanguage()
  print(clangs.name)
  clangs.say()
  可以看到,在创建类时,通过在标注父类的同时指定元类(格式为metaclass=元类名),则当 Python 解释器在创建这该类时,FirstMetaClass 元类中的 __new__ 方法就会被调用,从而实现动态修改类属性或者类方法的目的。
 
  运行上面的程序,输出结果为:
  C语言中文网
  调用 say() 实例方法
 
  显然,FirstMetaClass 元类的 __new__() 方法动态地为 Clanguage 类添加了 name 属性和 say() 方法,因此,即便该类在定义时是空类,它也依然有 name 属性和 say() 方法。
  对于 MetaClass 元类,它多用于创建 API,因此我们几乎不会使用到它。
 

(编辑:财气旺网 - 财气网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!