You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pytest monkeypatch打补丁Pydantic BaseModel方法时触发ValueError

解决Pydantic BaseModel实例用monkeypatch打补丁失败的问题

问题原因

Pydantic的BaseModel重写了__setattr__方法,会严格校验要设置的属性是否是模型定义的字段。你要补丁的intro是实例方法而非模型字段,直接用monkeypatch.setattr(p, 'intro', ...)会触发Pydantic的字段检查,抛出ValueError: "Person" object has no field "intro"错误。

解决方案

方案1:给类而非实例打补丁

直接修改Person类的intro方法,避开实例的字段检查,同时注意补丁函数要接收self参数(因为是实例方法):

from pydantic import BaseModel


class Person(BaseModel):
    name: str
    age: int

    def intro(self) -> str:
        return f"I am {self.name}, {self.age} years old."


def test_person_intro(monkeypatch):
    p = Person(name='Joe', age=20)
    # 给Person类的intro方法打补丁
    monkeypatch.setattr(Person, 'intro', lambda self: 'patched intro')
    assert p.intro() == 'patched intro'

方案2:直接操作实例的__dict__绕过检查

通过修改实例的__dict__属性设置方法,绕过Pydantic的__setattr__校验,同样要保证补丁函数接收self:

from pydantic import BaseModel


class Person(BaseModel):
    name: str
    age: int

    def intro(self) -> str:
        return f"I am {self.name}, {self.age} years old."


def test_person_intro(monkeypatch):
    p = Person(name='Joe', age=20)
    # 直接修改实例的__dict__
    monkeypatch.setattr(p.__dict__, 'intro', lambda self: 'patched intro')
    assert p.intro() == 'patched intro'

注意点

你原来写的lambda: 'patched intro'没有接收self参数,调用p.intro()时Python会自动把实例作为第一个参数传入,会导致参数不匹配报错,所以补丁函数必须加上self参数。

内容的提问来源于stack exchange,提问作者valcapp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:43:25