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

Python:如何从序列化形式重建对象而无需重新计算属性

推荐实现方案

1. 类工厂方法(最推荐,扩展性强)

给Link类添加一个类方法,直接从字典(JSON解析后的数据)创建实例,跳过原__init__里的自动生成ID和爬取逻辑:

from uuid import uuid4 as uuid
import requests
from bs4 import BeautifulSoup

class Link:
    def __init__(self, url):
        self.url = url
        self.id = str(uuid())
        self.content = self.scrape()

    def scrape(self):
        response = requests.get(self.url).text
        soup = BeautifulSoup(response, features="html.parser")
        return soup.get_text()
    
    @classmethod
    def from_dict(cls, data):
        # 创建实例但不调用__init__,避免触发scrape和ID生成
        instance = cls.__new__(cls)
        # 直接将字典中的所有属性赋值给实例
        instance.__dict__.update(data)
        return instance

使用时,把JSON解析成字典后传入即可:

import json

# 从数据库读取的JSON字符串
json_str = '''{
    "url": "https://example.com",
    "id": "ba664ae1-eb5d-4370-9276-93f8d9d03a0d",
    "content": "Example Domain Example Domain This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission. More information..."
}'''

data = json.loads(json_str)
link_obj = Link.from_dict(data)

这种方式不管后续新增多少字段(比如title),只要JSON里包含对应的键,就能自动赋值,完全不用修改工厂方法,扩展性极强。

2. 改用dataclass的简化方案

如果后续换成dataclass,可以结合类工厂方法,同样不用修改核心逻辑:

from dataclasses import dataclass
from uuid import uuid4 as uuid
import requests
from bs4 import BeautifulSoup

@dataclass
class Link:
    url: str
    id: str | None = None
    content: str | None = None

    def __post_init__(self):
        # 只有当id或content为空时,才执行自动生成和爬取逻辑
        if self.id is None:
            self.id = str(uuid())
        if self.content is None:
            self.content = self.scrape()

    def scrape(self):
        response = requests.get(self.url).text
        soup = BeautifulSoup(response, features="html.parser")
        return soup.get_text()
    
    @classmethod
    def from_dict(cls, data):
        return cls(**data)

这里利用__post_init__区分首次创建和从数据库重建的场景:首次实例化时不传id和content,就自动生成/爬取;从JSON重建时直接传入所有字段,__post_init__不会触发额外逻辑。from_dict只需要解包字典即可,新增字段时也不需要修改这个方法。

为什么不推荐修改__init__参数?

如果直接给__init__加一堆可选参数(比如id=None, content=None),后续每加一个字段都要修改__init__的参数列表,代码会越来越臃肿,维护成本高。而工厂方法的模式可以彻底避免这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:10:27