应避免直接修改内置类型或系统对象,优先通过封装、继承或工具函数扩展行为;若需动态添加方法,须用命名隔离和存在性检查;警惕变量名与内置名冲突。

核心思路是:不直接往内置类型或系统对象上挂方法,优先用封装、委托或命名隔离的方式扩展行为,避免污染全局命名空间和内置类型。
避开直接修改内置类型
Python 的 str、list、dict 等内置类型不允许动态添加属性(会报 AttributeError),但若你通过 monkey patch 方式强行给类加方法(如 str.my_upper = ...),不仅违反设计原则,还极易覆盖已有方法或引发不可预知冲突。
- 不要给内置类或标准库类动态赋值方法,例如:
str.format = my_custom_format是危险且非法的 - 如果真需扩展,应定义新类继承原类型,或使用独立工具函数,例如:
def safe_format(s: str, *args): ... - 对第三方库对象也同理——除非文档明确支持 monkey patch,否则一律视为只读接口
为自定义对象设置安全的动态扩展机制
若必须在运行时给某个对象添加函数,可通过字典隔离 + 命名前缀控制作用域,防止与原有方法重名。
- 用独立命名空间存储扩展函数,比如:
obj._ext_methods = {},所有动态添加的方法都存这里 - 调用时显式前缀,如
obj._ext_methods["validate_email"](obj),不混入obj.__dict__ - 添加前先检查是否已存在同名属性:
if not hasattr(obj, "my_handler"):,再赋值
用装饰器或协议约定替代硬覆盖
与其动态覆盖一个方法,不如设计成可插拔的行为注入点,让扩展更可控、更易测试。
- 在类中预留钩子方法(如
before_save()),默认空实现,子类或运行时通过setattr替换时,仅替换钩子,不碰主逻辑 - 使用
functools.singledispatch或自定义分发器,按参数类型路由到不同处理函数,避免同名覆盖 - 对关键方法加
@final(Python 3.8+)或自定义装饰器标记,配合__init_subclass__检查,提前拦截非法覆盖
警惕变量名与内置名冲突
函数表达式常被赋给变量,若变量名恰好撞上内置函数(如 list、max、filter),后续调用就会出错。
- 写完赋值语句后快速检查:
print(type(list))—— 如果输出<class 'int'>就说明你覆盖了内置list - 启用 IDE 的名称冲突提示(如 VS Code + Pylance),它能标出 shadowing built-in 的警告
- 统一约定:自定义函数/变量名加前缀,如
my_list_builder、safe_max,不图省事用单字

















