使用 pydantic + Mixins 模式的 ABC/接口问题

Tâm*_*iro 7 python oop mixins pydantic

我尝试实现 Mixin 模式,同时使用 PydanticsBaseClass来促进类中数据的实例化和验证。问题是我的 Mixins 无法继承我的基类(实际上,依赖关系是相反的)。另外,我使用 mypy 所以我的实现需要正确输入。

让我们看一个简化的例子:

class BaseCart(BaseModel):
    id: int
    items: List[Item]
    adress: str


class CartInterface(ABC):
    @abstractproperty
    def id(self):
        ...

    @abstractproperty
    def items(self):
        ...

    @abstractproperty
    def adress(self):
        ...

    @abstractmethod
    def get_shipping_value(self):
        ...

    @abstractmethod
    def get_items_availability(self):
        ...


class ShippingMixin(ABC, CartInterface):
    def get_shipping_value(self) -> int:
        # some business logic using self.address to calculate

class NormalItemsMixin(ABC, CartInterface):
    def get_items_availability(self) -> bool:
       # iterate over self.items and check stock availability

class AwesomeItemsMixin(ABC, CartInterface):
    def get_items_availability(self) -> bool:
       # iterate over self.items and check stock availability
       # this implementation is different from the normal one

class NormalCart(BaseCart, ShippingMixin, NormalItemsMixin):
    ...

class AwesomeCart(BaseCart, ShippingMixin, AwesomeItemsMixin):
    ...
Run Code Online (Sandbox Code Playgroud)

问题是,实现此后,我无法实例化AwesomeCart,出现以下错误: TypeError: Can't instantiate abstract class ResellerCart with abstract methods business_unit, cart_type, channel, id, items, reseller, status, updated_at

我缺少什么?

TLDR:为什么会这样


class Data(BaseModel):
    a: int

class IData(ABC):
    @abstractproperty
    def a(self):
        ...

class XData(Data, IData):
    ...
Run Code Online (Sandbox Code Playgroud)

TypeError: Can't instantiate abstract class XData with abstract method a当我实例化XData喜欢时引发x = XData(a=1)

Nic*_*fan 3

在 IData 中,a它只是“伪装”为属性,而实际上它是类的方法。你必须做类似的事情

class Data(BaseModel):
    _a: int

    @property
    def a(self):
        return self._a


class IData(ABC):
    @abstractproperty
    def a(self):
        pass


class XData(Data, IData):
    pass

Run Code Online (Sandbox Code Playgroud)

现在ainData也是一个方法,代码按预期工作。


@abstractproperty自 python 3.3 起已弃用,请使用“property”和“abstractmethod”代替。

class IData(ABC):
    @property
    @abstractmethod
    def a(self):
        pass
Run Code Online (Sandbox Code Playgroud)