简体   繁体   English

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

[英]Inherite dataclass using base instance Python

I have two dataclasses inside bookmodel , one inherited from the other:我在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

Then in another .py file, I need to init a ClientOrder instance using BookOrder :然后在另一个.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!!!

Since BookOrder is NOT callable, I cannot pass self.id to it.由于BookOrder不可调用,因此我无法将self.id传递给它。 I was wondering if there's an elegant way to achieve this?我想知道是否有一种优雅的方式来实现这一目标?

Update更新

Guess what I am trying to ask is, is there any other way to initialize a ClientOrder using BookOrder other than the below method?猜猜我想问的是,除了下面的方法之外,还有其他方法可以使用BookOrder初始化ClientOrder吗?

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

One way to solve this is by not using inheritance, and instead declaring client_id as an optional attribute instead.解决此问题的一种方法是不使用继承,而是将client_id声明为可选属性。 Since the BookOrder dataclass is also frozen, we then need to call object.__setattr__ to modify the value of client_id , as mentioned in this post .由于BookOrder数据类也被冻结了,然后我们需要调用object.__setattr__修改的值client_id ,在提到这个职位

In your first module a.py :在你的第一个模块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

In second module b.py :在第二个模块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:
        #  https://stackoverflow.com/a/59249252/10237506
        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))

Outputs:输出:

Successfully set client_id attribute: 'abc123'

Of course, the easier way is to just not define it as frozen dataclass:当然,更简单的方法是不将其定义为frozen数据类:

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

And then the only change needed in b.py :然后在b.py需要的唯一更改:

    ...

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM