惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
小众软件
小众软件
S
SegmentFault 最新的问题
人人都是产品经理
人人都是产品经理
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
C
Check Point Blog
S
Schneier on Security
Microsoft Azure Blog
Microsoft Azure Blog
N
Netflix TechBlog - Medium
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
罗磊的独立博客
有赞技术团队
有赞技术团队
V
V2EX
Y
Y Combinator Blog
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Fortinet All Blogs
W
WeLiveSecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
The Cloudflare Blog
S
Security @ Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
PCI Perspectives
PCI Perspectives
H
Heimdal Security Blog
Schneier on Security
Schneier on Security
Security Latest
Security Latest
AWS News Blog
AWS News Blog
月光博客
月光博客
Security Archives - TechRepublic
Security Archives - TechRepublic
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
博客园 - Franky
Cisco Talos Blog
Cisco Talos Blog
T
Threat Research - Cisco Blogs
M
MIT News - Artificial intelligence
T
Troy Hunt's Blog
N
News and Events Feed by Topic
Cloudbric
Cloudbric
Scott Helme
Scott Helme
云风的 BLOG
云风的 BLOG
Attack and Defense Labs
Attack and Defense Labs

博客园 - 箫笛

Tkinter - Button 组件 Tkinter - Label 组件 Tkinter - tk 变量 Tkinter - 事件与绑定 Tkinter - 几何管理器 Tkinter - 核心概念 Tkinter - 快速开始 Tkinter - 介绍 Python 编程 - 条件表达式 Python 编程 - 星号下划线参数释义 shell 编程 - shell 脚本的交互方式 Python insall - macOS 系统安装python的几种方式 Miniconda - Python 环境管理工具 Tkinter - Python GUI 开发 Python 编程 - 下划线命名的区别 Python 编程 - 多重继承与MRO Python 编程 - 描述符协议 Python 编程 - 类型注解 Python 编程 - 生成器表达式 Python 编程 - 集合 Python 编程 - 装饰器 Python 编程 - 闭包 Python 编程 - 列表推导式 Python 编程 - 函数式编程 Python 编程 - lambda 函数 Python 编程 - 文件操作 Python 编程 - 输入与输出 Python 编程 - 面向对象编程 Python 编程 - 元组(tuple) Python 编程 - 字符串(str) Python 编程 - 字典(dict) Python 编程 - 列表(list) Python 编程 - 数据类型和数据结构 Python 编程 - 语句 Python 编程 - 函数 windows - WSL 的安装与使用 shell编程 - dialog 程序使用指南 FE Team - 如何做好前端代码审查 git 提交的撤销和恢复 React15 - redux-saga 如何在saga中实现轮询接口调用? React15 - React CSS Modules BEM命名实践 React15 - React 15 中 componentWillReceiveProps 为什么会多次调用, 同时componentDidUpdate 也会多次调用? React15 - React15类组件多次执行render方法的原因? React15 - React15应用中代码逻辑复用方案 React15 - React状态同步问题解决 React15 - React 15 中 React.pureComponent 的使用场景 React15 - React 15应用在页面渲染时会多次执行类组件的render 函数的原因 React15 - React 15 中能用 componetDidUpdate 代替 componentWillReceiveProps 吗? React15 - React 15 生命周期函数详解 React15 - 如何在React 15中实现自定义的事件订阅与发送(例如组件间通信) React15 - React15应用中的事件订阅和发送机制 React15 - CSS中的BEM规范 React15 - React CSS Modules BEM命名实践 React15 - 写sass 样式文件,嵌套的结构好,还是扁平的结构好? React15 - sass 中 @mixin 和 @extend 的区别是什么? React15 - React 15 应用 如何使用Css moudules 方式进行模块化开发 React15 - React15应用Sass使用指南 React15 - React 15 应用如何进行性能优化?
Python 编程 - 元类编程
箫笛 · 2026-07-03 · via 博客园 - 箫笛

什么是元类

要理解元类(Metaclass),可以这样类比:是用来创建对象的蓝图;而元类,则是用来创建的蓝图。如果说类是对象的“工厂”,那么元类就是生产这些“工厂”的“总工厂”。

在 Python 中,一切皆对象,类本身也不例外。一个类,它是其元类的一个实例。

一切的起源:type

type 是 Python 内置的默认元类,所有类(包括 intstr 等)都是 type 的实例。

你可以通过 type() 函数来验证一个对象的类型,也可以使用它来动态地创建类

type(name, bases, dict) 接收三个参数,动态地返回一个新的类:

  • name:类的名称(字符串)
  • bases:父类的元组(用于继承)
  • dict:包含属性(方法)的字典
# 使用 class 语句定义类
class Hello:
    def say_hello(self):
        print("Hello!")

# 等价于使用 type 动态创建
def say_hello(self):
    print("Hello!")

Hello = type('Hello', (), {'say_hello': say_hello})

# 两者创建出的类是完全一样的

当 Python 解释器遇到 class 关键字时,它背后的工作就是调用元类(默认是 type)来创建这个类。

自定义元类:掌控类的创建

要创建自定义元类,需要继承 type。你可以重写它的几个关键方法,在类创建的不同阶段进行干预。

1. __new__ 方法:类的“构造器”

这是创建类对象时第一个被调用的方法。它在类的名称、基类、属性字典准备好后被调用。你可以在这里修改类的属性字典(例如,添加、删除或修改属性和方法),然后再调用 super().__new__ 真正创建类。

class UpperAttrMeta(type):
    def __new__(cls, name, bases, namespace):
        # 将类中所有非特殊属性名转为大写
        upper_namespace = {
            key.upper(): value 
            for key, value in namespace.items() 
            if not key.startswith('__')
        }
        # 使用修改后的命名空间创建类
        return super().__new__(cls, name, bases, upper_namespace)

class Demo(metaclass=UpperAttrMeta):
    x = 10

print(Demo.X)  # 输出: 10
# print(Demo.x)  # 报错: AttributeError

2. __init__ 方法:类的“初始化器”

__new__ 创建类对象之后被调用,通常用于对已经创建好的类进行进一步的初始化或设置。

3. __call__ 方法:控制类的实例化

通过类创建实例时(即 MyClass()),实际上是调用了元类的 __call__ 方法。重写此方法可以控制实例的创建和初始化过程,是实现单例模式(Singleton)的关键。

class SingletonMeta(type):
    def __init__(cls, *args, **kwargs):
        cls.__instance = None
        super().__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = super().__call__(*args, **kwargs)
        return cls.__instance

class MyClass(metaclass=SingletonMeta):
    pass

a = MyClass()
b = MyClass()
print(a is b)  # 输出: True

4. __prepare__ 方法:准备类的命名空间

在类的定义体开始执行前被调用,它返回一个字典或映射对象,用于存储类定义体中的属性和方法。在 Python 3 中,这是唯一一个在类体执行前运行的元类方法,极少使用,通常用于控制类中属性的定义顺序等高级场景。

使用场景与注意事项

何时使用?
元类常用于框架和库的开发中,以实现高度抽象和自动化:

  • 对象关系映射(ORM):如 Django 和 SQLAlchemy,利用元类将数据库表自动映射为 Python 类。
  • 实现单例模式:确保一个类只有一个实例。
  • 自动注册类:在类创建时将其自动注册到某个全局注册表中。
  • 强制编码规范:检查类是否定义了必须的方法或属性。
  • 实现抽象基类(ABC):Python 内置的 abc 模块就是通过 ABCMeta 这个元类来实现的。

注意事项

元类是 Python 中最复杂、最难理解的特性之一。它强大,但也容易被滥用。在绝大多数情况下,更简单的解决方案(如类装饰器、描述符或继承)是更好的选择。请务必谨记 “KISS 原则”(Keep It Simple, Stupid),仅在确实需要动态且全局地控制类创建行为时才考虑使用元类。