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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 06:37:03