使用基本实例继承数据类 Python

Inherite dataclass using base instance Python

我在 bookmodel 中有两个数据类,一个继承自另一个:

@dataclass(frozen=True)
class BookOrder:
    category: str
    name: str
    color: str
    price: int
    volume: int

@dataclass(frozen=True)
class ClientOrder(BookOrder):
    client_id: str

然后在另一个 .py 文件中,我需要使用 BookOrder:

初始化一个 ClientOrder 实例
from book_model import BookOrder
# ...

@dataclass
class Client:
    id: str
    def place_book_order(self, book_order: BookOrder):
        # want to init a ClientOrder HERE!!!

由于 BookOrder 不可调用,我无法将 self.id 传递给它。我想知道是否有一种优雅的方法可以实现这一目标?

更新

猜猜我想问的是,除了下面的方法之外,还有其他方法可以使用 BookOrder 初始化 ClientOrder 吗?

client_order=ClientOrder(book_order.categry, book_order.name, ..., self.client_id)

解决这个问题的一种方法是不使用继承,而是将 client_id 声明为可选属性。由于BookOrder数据类也被冻结了,我们接下来需要调用object.__setattr__来修改client_id的值,如.

中所述

在你的第一个模块中 a.py:

from __future__ import annotations  # Added for compatibility with 3.7+

from dataclasses import dataclass


@dataclass(frozen=True)
class BookOrder:
    category: str
    name: str
    color: str
    price: int
    volume: int
    client_id: str | None = None

在第二个模块中 b.py:

from book_model import BookOrder
# ...

@dataclass
class Client:
    id: str
    def place_book_order(self, book_order: BookOrder):
        # The following does not work, because BookOrder is a frozen
        # dataclass.
        # setattr(book_order, 'client_id', self.id)
        # Use object.__setattr__ as mentioned here:
        #  
        object.__setattr__(book_order, 'client_id', self.id)

        if book_order.client_id:
            print('Successfully set client_id attribute:',
                  repr(book_order.client_id))
        else:
            print('Was unable to set client_id attribute on frozen dataclass')


Client('abc123').place_book_order(BookOrder(*['a'] * 5))

输出:

Successfully set client_id attribute: 'abc123'

当然,更简单的方法是不将其定义为 frozen dataclass:

@dataclass
class BookOrder:
    category: str
    name: str
    color: str
    price: int
    volume: int
    client_id: str | None = None

然后 b.py 中唯一需要的更改:

    ...

    def place_book_order(self, book_order: BookOrder):
        book_order.client_id = self.id
        ...