如何在Pydantic中重写父类的@property装饰属性
解决Pydantic子类重写父类@property属性的问题
问题原因
父类中用@property装饰的name_new会被Pydantic识别为模型属性,子类直接赋值name_new = 'foo_bar_foo'会被当成新字段,和父类属性冲突导致报错。而使用alias的方式只是创建了一个别名字段,并不会覆盖父类的@property方法,所以访问c.name_new时仍然调用父类的逻辑。
解决方案
方案1:直接重写子类的@property方法
在子类中重新定义带@property装饰的name_new方法,直接覆盖父类的实现:
from pydantic import BaseModel class Parent(BaseModel): name: str = 'foo bar' @property def name_new(self): return f"{'_'.join(self.name.split(' '))}" class Child(Parent): @property def name_new(self): return 'foo_bar_foo' c = Child() print(c.name_new) # 输出: foo_bar_foo
方案2:将name_new转为子类的字段(可选)
如果希望name_new作为Pydantic的可序列化字段,而非动态计算的property,可以在子类中定义该字段,并通过配置确保父类的property被覆盖:
from pydantic import BaseModel class Parent(BaseModel): name: str = 'foo bar' @property def name_new(self): return f"{'_'.join(self.name.split(' '))}" class Child(Parent): name_new: str = 'foo_bar_foo' model_config = { # 确保字段优先于父类的property 'fields': {'name_new': {'alias': 'name_new'}} } c = Child() print(c.name_new) # 输出: foo_bar_foo print(c.model_dump()) # 输出: {'name': 'foo bar', 'name_new': 'foo_bar_foo'}
说明
- 方案1适合仅需改变动态计算逻辑的场景,保持
name_new为只读属性。 - 方案2适合需要将
name_new作为可配置、可序列化的模型字段的场景。
内容的提问来源于stack exchange,提问作者George Liu
相关产品推荐
相关产品推荐

