Python 元类与异常类:类的“制造工厂”与“报错定制师”

文章目录

前言

[第一章:元类 ------ 类的"制造工厂"](#第一章:元类 —— 类的“制造工厂”)

[1.1 万物皆对象,类也是对象](#1.1 万物皆对象,类也是对象)

[1.2 type() 动态创建类](#1.2 type() 动态创建类)

[1.3 自定义元类 ------ 给"类创建过程"加钩子](#1.3 自定义元类 —— 给“类创建过程”加钩子)

[1.4 元类与装饰器的区别](#1.4 元类与装饰器的区别)

[第二章:异常类 ------ 定制你自己的"报错"](#第二章:异常类 —— 定制你自己的“报错”)

[2.1 为什么需要自定义异常?](#2.1 为什么需要自定义异常?)

[2.2 基础写法:继承 Exception](#2.2 基础写法:继承 Exception)

[2.3 带额外信息的异常类](#2.3 带额外信息的异常类)

[2.4 异常类体系](#2.4 异常类体系)

[2.5 什么时候用自定义异常?](#2.5 什么时候用自定义异常?)

[🧁 结尾](#🧁 结尾)

前言

今天聊两个"高阶"但很酷的概念------元类异常类

元类 是"制造类的类"------它决定了类怎么被创建。你写的每个类,背后都是元类在干活。

异常类 是"定制报错"------Python 自带的异常够用,但你也可以自己造新的异常类型,携带更精确的错误信息。

一个管"生",一个管"死"(报错也算一种"死")

next let me show🏭

第一章:元类 ------ 类的"制造工厂"

1.1 万物皆对象,类也是对象

在 Python 里,一切皆对象:数字是对象,字符串是对象,类也是对象

既然类是对象,那它肯定是由某个"类"创建出来的。这个创建类的类,就叫 元类(Metaclass)

python

复制代码
class MyClass:
    pass

# 查看 MyClass 的类型
print(type(MyClass))   # <class 'type'>

📌 默认情况下,所有类的元类都是 typetype 就是 Python 内置的元类,负责创建所有的类。

1.2 type() 动态创建类

除了 class 关键字,你可以直接用 type() 函数动态创建类:

python

复制代码
# 用 type 创建类:type(类名, 父类元组, 属性字典)
MyDynamicClass = type("MyDynamicClass", (), {"x": 10, "hello": lambda self: "world"})

obj = MyDynamicClass()
print(obj.x)          # 10
print(obj.hello())    # world

这和用 class 定义的效果一样,只不过是在运行时动态生成的。

1.3 自定义元类 ------ 给"类创建过程"加钩子

你可以继承 type,重写 __new____init__,在类被创建时插入自定义逻辑。

最常见场景:自动给类添加属性或方法,或者做参数校验

python

复制代码
class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        # 自动给类加一个属性
        attrs["version"] = "1.0"
        # 或者检查类名不能以数字开头等
        return super().__new__(cls, name, bases, attrs)

# 使用 metaclass 参数指定元类
class MyClass(metaclass=MyMeta):
    pass

print(MyClass.version)   # 1.0(自动加上的)

📌 元类很强大,但也很少需要自己写。99% 的情况你不需要自定义元类。但理解它,有助于你理解 ORM(比如 Django 的 Model)、单例模式等底层机制。

1.4 元类与装饰器的区别

维度 装饰器 元类
作用对象 函数或类(实例) 类本身(创建过程)
时机 运行时(调用时) 类定义时(编译时)
修改能力 修改类的行为 修改类的结构(添加/删除属性、方法)
复杂度

|----------|----------------------|
| 外部服务调用失败 | ThirdPartyAPIError |
| 数据验证失败 | ValidationError |

第二章:异常类 ------ 定制你自己的"报错"

2.1 为什么需要自定义异常?

Python 内置了很多异常:ValueErrorTypeErrorKeyError......但有时候你想更精确地描述错误 ,或者携带额外信息(比如出错时的具体数值)。

这时候你就需要自定义异常类。

2.2 基础写法:继承 Exception

自定义异常类必须继承自 Exception 或其子类。最简单的只需要一个 pass

python

复制代码
class MyCustomError(Exception):
    pass

try:
    raise MyCustomError("出错了!")
except MyCustomError as e:
    print(e)   # 出错了!

2.3 带额外信息的异常类

你可以重写 __init__,给异常加上更多属性:

python

复制代码
class AgeTooOldError(Exception):
    def __init__(self, age, limit=100):
        self.age = age
        self.limit = limit
        super().__init__(f"年龄 {age} 超过最大限制 {limit}")

# 使用
def set_age(age):
    if age > 100:
        raise AgeTooOldError(age)
    print(f"年龄设置为 {age}")

try:
    set_age(150)
except AgeTooOldError as e:
    print(f"错误:{e}")
    print(f"你输入的年龄是 {e.age},最大允许 {e.limit}")

输出:

text

复制代码
错误:年龄 150 超过最大限制 100
你输入的年龄是 150,最大允许 100

💡 这样调用者就能通过 e.age 拿到具体数值,方便做日志或提示。

2.4 异常类体系

你可以构建自己的异常体系,比如:

python

复制代码
class MyAppError(Exception):
    """应用根异常"""
    pass

class DatabaseError(MyAppError):
    """数据库相关错误"""
    pass

class NetworkError(MyAppError):
    """网络相关错误"""
    pass

这样在 except MyAppError 时能捕获所有自定义异常,而更细分的异常可以单独处理。

2.5 什么时候用自定义异常?

场景 示例
业务逻辑校验失败 BalanceNotEnoughError
配置错误 ConfigNotFoundError
外部服务调用失败 ThirdPartyAPIError
数据验证失败 ValidationError

🎯 一张图总结

text

复制代码
元类(制造类)
        默认:type
        自定义:继承 type,重写 __new__/__init__
        用途:ORM、单例、自动注册
 记住:99% 情况用不到

异常类(定制报错)
         继承 Exception
        添加 __init__ 携带额外信息
         构建异常体系(根异常 + 子异常)
 用途:精确错误类型 + 携带数据

🧁 结尾

元类 是"造类的机器",默认是 type。自定义元类能让你在类诞生时"插一脚",但大部分情况你不需要自己写。

异常类 是"报错定制师",继承 Exception 加自己的属性和方法,让报错信息更精准、更友好。

相关推荐
quantdash_cc2 小时前
基于 QuantDash 5 分钟 K 线的网格交易策略参数网格搜索寻优实战
android·开发语言·pandas·量化·quantdash
147API2 小时前
Python批量生成蒸馏数据,并发、重试、幂等和断点续跑
开发语言·jvm·python
青 春 记 忆2 小时前
零基础入门python04:用注册校验理解字典、集合和条件判断
开发语言·vscode·python·python3.11
kels88992 小时前
实战排坑:黄金实时API开发,XAUUSD Tick报文异常处理实践
开发语言·python·websocket·网络协议·信息可视化
阿pin2 小时前
Java随笔-JDK7 HashMap头插法为何能导致死循环?
java·开发语言·hashmap
FBI HackerHarry浩2 小时前
Pandas 库中用于分类变量独热编码(One-Hot Encoding)的函数 pd.get_dummies() 函数
开发语言·人工智能·python·pandas
高洁012 小时前
工信部教考中心证书-人工智能系列本系列
人工智能·python·深度学习·算法
名字还没想好☜2 小时前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go
李可以量化2 小时前
Tornado 从入门到精通(二)下:协程调用方式与经典使用模式
python