Python元类type详解:从基础创建到高级应用

Cora
Cora
发布时间:2026-10-13 | 5人浏览过
原创

本文深入解析Python中元类type的核心机制。从使用type动态创建类及其方法开始,详细讲解如何通过指定__metaclass__属性来拦截类的创建过程。通过函数和自定义类两种实现方式,演示如何对类名、父类及属性进行预处理,如属性名大写转换。文章结合代码示例,帮助开发者理解元类在框架开发和ORM设计中的实际应用。

Python元类type基础概念

本文详细介绍Python中利用元类type构建类对象的常见应用场景,供读者参考学习。

通过 type("123") 可以检查变量的类型;而使用 type("类名",(父类),{类属性:值,类属性2:值}) 则能够动态创建一个类。

Python通常不推荐一个函数承担多种不同功能(即函数重载),type()之所以具备多种形态,主要是为了兼容早期版本的设计。

类用于创建实例对象,而类本身则由元类创建。简而言之,元类负责创建类,类负责创建实例对象。

type本身就是元类,其本质是一个类。

使用type动态创建类

以下demo.py代码展示了如何使用元类type来创建类:


# 通过class关键字创建类
class MyClass1(object):
  name = "张三" # 类属性 (所有实例对象共用)
  age = 23
# 通过type创建类。 type()返回的是创建的类对象的引用。
Test2 = type("MyClass2",(object,),{"name":"张三","age":23}) # Test2是MyClass2类的引用,一般变量名和类名保持一致。
print(Test2()) # <__main__.MyClass2 object at 0x7fa05a4ca9e8>

以下demo.py代码演示了如何使用type创建包含方法的类:


# 实例方法
def print_b(self):
  print(self.num)
# 静态方法
@staticmethod
def print_static():
  print("----haha-----")
# 类方法
@classmethod
def print_class(cls):
  print(cls.num)
# 用type创建类
B = type("B", (object,), {"num":100, "print_b": print_b, "print_static": print_static, "print_class": print_class})
b = B()
b.print_b()   # 100
b.print_static() # ----haha-----
b.print_class()  # 100

元类的高级应用与拦截

元类的具体应用场景

在定义类时,可以通过指定__metaclass__属性来指定创建该类的元类,若不指定,默认使用type元类来创建类对象。

通过自定义元类,可以拦截类的创建过程,并对类名、继承的父类以及属性(方法)进行预处理。

例如,可以将类名转换为大写,默认继承object类,或者添加、修改属性(方法)的名称。私有属性的伪私有化正是通过修改属性名来实现的。

装饰器用于在不修改原代码的情况下扩展函数功能,而元类则用于在不修改原类的情况下扩展类的功能(如添加额外的属性或方法)。

以下demo.py代码展示了如何使用函数来指定__metaclass__属性:


#-*- coding:utf-8 -*-
def upper_attr(class_name, class_parents, class_attr):
  # class_name 会保存类的名字 Foo
  # class_parents 会保存类的父类 object
  # class_attr 会以字典的方式保存所有的类属性/方法
  # 遍历属性字典,把不是__开头的属性名字变为大写
  new_attr = {}
  for name, value in class_attr.items():
    if not name.startswith("__"):
      new_attr[name.upper()] = value
  # 调用type来创建一个类
  return type(class_name, class_parents, new_attr)
class Foo(object, metaclass=upper_attr): # python3的方式
  # python2.x的方式。
  # __metaclass__ = upper_attr # 设置Foo类的元类为upper_attr
  bar = 'bip'
print(hasattr(Foo, 'bar'))
print(hasattr(Foo, 'BAR'))
f = Foo()
print(f.BAR)

以下demo.py代码展示了如何使用类来指定__metaclass__属性:


class UpperAttrMetaClass(type):
  # __new__ 是在__init__之前被调用的特殊方法
  # __new__是用来创建对象并返回之的方法
  # 而__init__只是用来将传入的参数初始化给对象
  # 你很少用到__new__,除非你希望能够控制对象的创建
  # 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__
  # 如果你希望的话,你也可以在__init__中做些事情
  # 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用
  def __new__(cls, class_name, class_parents, class_attr):
    # 遍历属性字典,把不是__开头的属性名字变为大写
    new_attr = {}
    for name, value in class_attr.items():
      if not name.startswith("__"):
        new_attr[name.upper()] = value
    # 方法1:通过'type'来做类对象的创建
    return type(class_name, class_parents, new_attr)
    # 方法2:复用type.__new__方法
    # 这就是基本的OOP编程,没什么魔法
    # return type.__new__(cls, class_name, class_parents, new_attr)
# python3的用法
class Foo(object, metaclass=UpperAttrMetaClass):
  bar = 'bip'
# python2的用法
# class Foo(object):
#   __metaclass__ = UpperAttrMetaClass
#   bar = 'bip'
print(hasattr(Foo, 'bar'))
# 输出: False
print(hasattr(Foo, 'BAR'))
# 输出:True
f = Foo()
print(f.BAR)
# 输出:'bip'

对Python感兴趣的其他读者,可参考本站相关专题:《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》。

希望本文的内容能对大家的Python程序设计有所帮助。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表