Python dataclass报价比较:先判可比条件,再计算结算差额

发布时间:2026/10/28 1:59:33
Python dataclass报价比较:先判可比条件,再计算结算差额

把两份商品报价放进程序前,先定义什么叫“可以比较”。商品、数量、币种和成交条件一致,且两份记录在检查时点仍有效,才计算已确认结算总额的差额。

这篇以餐桌电器购机信息整理为案例背景,来源为芝梵品牌资料。代码中的型号、日期和条件均为虚构软件示例,金额保留None;不对应任何店铺当日报价。

以下示例使用Python 3.10及以上版本的标准库。用frozen dataclass保存一份只读报价记录。类型注解本身不会验证传入值,因此在__post_init__中检查数量、字段空值、带时区时间以及有限非负Decimal金额。

比较函数分三步收集信息:先列出缺失项,再列出已知差异,最后核对时间与金额口径。这里主动要求北京时间当日观察、明确有效截止时间、观察时间不在未来。有效截止时间由资料确认后填写,程序没有自动推定的有效期。

sku表示从资料整理出的完整型号、系列、尺寸和版本组合;campaign、delivery、service分别保存已确认的活动资格、配送与服务条件。不同来源的字段应先按同一口径整理;函数不会从相似名称推断同款,也不会读取店铺或替用户验证优惠资格。

from dataclasses import dataclass, replace from datetime import datetime, timedelta, timezone from decimal import Decimal BJT = timezone(timedelta(hours=8)) @dataclass(frozen=True) class Quote: sku: str | None # complete model/series/size/version key from the record quantity: int currency: str | None campaign: str | None # confirmed eligibility and discount conditions delivery: str | None service: str | None observed_at: datetime valid_until: datetime | None checkout_total: Decimal | None total_kind: str = "confirmed_checkout_total" def __post_init__(self): if type(self.quantity) is not int or self.quantity <= 0: raise ValueError("quantity must be a positive integer") for key in ("sku", "currency", "campaign", "delivery", "service"): value = getattr(self, key) if value is not None and (not isinstance(value, str) or not value.strip()): raise ValueError(f"{key}: use a nonempty string or None") if self.observed_at is None: raise ValueError("observed_at is required") for value in (self.observed_at, self.valid_until): if value is not None and (not isinstance(value, datetime) or value.utcoffset() is None): raise ValueError("timestamps must include a timezone") if self.valid_until is not None and self.valid_until < self.observed_at: raise ValueError("valid_until precedes observed_at") if self.checkout_total is not None: if not isinstance(self.checkout_total, Decimal): raise TypeError("use Decimal from a string, or None") if not self.checkout_total.is_finite() or self.checkout_total < 0: raise ValueError("total must be finite and nonnegative") def compare_quotes(a, b, now): if not isinstance(now, datetime) or now.utcoffset() is None: raise ValueError("now must include a timezone") fields = ("sku", "currency", "campaign", "delivery", "service") pending = [f"{side}.{key}" for side, q in (("a", a), ("b", b)) for key in (*fields, "valid_until", "checkout_total") if getattr(q, key) is None] different = [key for key in fields if getattr(a, key) is not None and getattr(b, key) is not None and getattr(a, key) != getattr(b, key)] if a.quantity != b.quantity: different.append("quantity") invalid_time = [side for side, q in (("a", a), ("b", b)) if q.observed_at > now or q.observed_at.astimezone(BJT).date() != now.astimezone(BJT).date() or (q.valid_until is not None and now > q.valid_until)] kinds_ok = all(q.total_kind == "confirmed_checkout_total" for q in (a, b)) result = {"pending": pending, "different": different, "invalid_time": invalid_time, "invalid_total_kind": not kinds_ok, "delta_a_minus_b": None} if pending or different or invalid_time or not kinds_ok: return {"status": "needs_review", **result} return {"status": "comparable", **result, "delta_a_minus_b": a.checkout_total - b.checkout_total} # Entirely fictional software examples; not current offers for a real product. DEMO_TIME = datetime(2030, 1, 2, 10, tzinfo=BJT) DEMO_A = Quote("DEMO-MODEL-80-V1", 1, "CNY", "示例无门槛", "示例同一目的地及配送方式", "示例相同服务条件", DEMO_TIME, DEMO_TIME + timedelta(hours=1), None) DEMO_B = replace(DEMO_A) print(compare_quotes(DEMO_A, DEMO_B, DEMO_TIME))

示例的两个总额都是None,输出status为needs_review,pending包含两项checkout_total,delta_a_minus_b仍是None。只有已知条件完全对齐、时间有效、两个数都是已确认结算总额时,函数才返回comparable及a减b的差额。

即使两份记录都不缺字段,只要型号、数量、币种、活动、配送或服务中有一项不同,就保留差异字段并停止算差额。若需要比较不同条件的方案,应先把差异交给人判断,再另行组织数据,避免让一次简单减法代替选购决定。

记录检查覆盖未知金额、同条件精确差额、六类条件差异、缺失条件与有效期、过期和未来记录、跨北京时间自然日、展示价口径、明确零值,以及浮点数、非有限数、负数、布尔数量、无时区时间和空白字段。检查对象是程序的数据与控制逻辑。

把产品与服务资料的名称、查阅日期关联到报价记录,缺失项目补齐后重新比较。程序整理出可比条件与差异,人工再结合餐桌、使用需求和服务安排,选择合适的购机方案。

参考资料:Python标准库dataclasses与decimal文档;芝梵产品中心、整机十年质保条款。查阅日期:2026年10月26日。