如何用Python Dataclass实现PATCH方法的部分更新(仅初始化传入参数)
实现支持PATCH部分更新的Dataclass(仅初始化传入参数)
方法一:自定义partial_dataclass装饰器
核心思路是替换默认的__init__方法,仅为传入的参数赋值,未传入的字段不进行初始化(不会出现在实例属性中),从根源避免默认值导致的数据库误更新问题。
实现代码
from dataclasses import dataclass, fields from typing import TypeVar, Type, Optional import datetime T = TypeVar('T') def partial_dataclass(cls: Type[T]) -> Type[T]: # 先应用标准dataclass装饰器,禁用默认初始化方法 cls = dataclass(cls, init=False) def __init__(self, **kwargs): # 遍历类定义的所有字段,仅为传入的参数赋值 for field in fields(cls): if field.name in kwargs: setattr(self, field.name, kwargs[field.name]) cls.__init__ = __init__ return cls # 使用自定义装饰器定义目标类 @partial_dataclass class Person: id: int first_name: Optional[str] last_name: Optional[str] birthday: Optional[datetime.date]
使用示例
# 仅传入部分参数初始化实例 person = Person(id=1, first_name='Andrew') # 访问已初始化的字段 print(person.id) # 输出: 1 print(person.first_name) # 输出: 'Andrew' # 未传入的字段未被初始化,访问会触发AttributeError # print(person.last_name) # 报错: AttributeError: 'Person' object has no attribute 'last_name'
方法二:结合__post_init__过滤轻量场景
如果不想自定义装饰器,可以在标准dataclass基础上,用MISSING标记默认值,初始化后手动删除未传入的字段:
from dataclasses import dataclass, fields, MISSING from typing import Optional import datetime @dataclass(init=True) class Person: id: int first_name: Optional[str] = MISSING last_name: Optional[str] = MISSING birthday: Optional[datetime.date] = MISSING def __post_init__(self): # 删除未传入的字段(值为MISSING的属性) to_remove = [f.name for f in fields(self) if getattr(self, f.name) is MISSING] for name in to_remove: delattr(self, name)
使用示例
person = Person(id=1, first_name='Andrew') print(person.__dict__) # 输出: {'id': 1, 'first_name': 'Andrew'}
适配数据库PATCH更新的实践
生成数据库更新语句时,只需遍历实例的__dict__获取已初始化的字段,确保仅更新传入的参数:
def generate_patch_sql(instance, table_name: str) -> tuple[str, list]: update_fields = [] update_values = [] # 提取需要更新的字段和值(排除id作为WHERE条件) for key, value in instance.__dict__.items(): if key != 'id': update_fields.append(f"{key} = %s") update_values.append(value) update_values.append(instance.id) sql = f"UPDATE {table_name} SET {', '.join(update_fields)} WHERE id = %s" return sql, update_values # 使用示例 sql, params = generate_patch_sql(person, 'persons') print(sql) # 输出: UPDATE persons SET first_name = %s WHERE id = %s print(params) # 输出: ['Andrew', 1]
内容的提问来源于stack exchange,提问作者autoescape_on
相关产品推荐
相关产品推荐

