正确的方法来实现ABC SubClass

问题描述 投票:2回答:2

我有一个Interface类,它定义了对一个活动的“使用中”类的要求:

class Portfolio(ABC):
    @abstractmethod
    def update_portfolio(self):
        raise NotImplementedError

    @abstractmethod
    def update_from_fill(self):
        raise NotImplementedError

    @abstractmethod
    def check_signal(self, signal_event):
        raise NotImplementedError

方法update_portfolio和update_from_fill都是99%的必需案例中相同的方法。只有check_signal方法会有所不同。因此,为了避免不得不一次又一次地编写相同的代码,我已经为update_portfolio和update_from_fill定义了一个带有默认方法的基类:

class BaseBacktestPortfolio(Portfolio):
    def __init__(self, ...):
        ...

    def update_portfolio(self, ...):
        ...

    def update_from_fill(self, ...):
        ...

然后,最后,我有一个继承自BacktestPortfolio类的类,它指定了check_signal方法的正确实现:

class USBacktestPortfolio(BaseBacktestPortfolio):
    def check_signal(self, ...):
        ...

现在,问题是我的编辑抱怨BacktestPortfolio分类没有所有必需的抽象方法。当然,我可以忽略这一点,但完美的情况是,如果我能确保不可能从BacktestPortfolio类中实例化一个对象。

这可能吗?和/或有没有更正确的方法来实现这样的结构?

python python-3.x abstract-class
2个回答
0
投票

您可以将BaseBacktestPortfolio也作为抽象类。

from abc import ABC, abstractmethod

class Portfolio(ABC):
    @abstractmethod
    def update_portfolio(self):
        pass

    @abstractmethod
    def update_from_fill(self):
        pass

    @abstractmethod
    def check_signal(self, signal_event):
        pass

class BaseBacktestPortfolio(Portfolio, ABC):

    def update_portfolio(self):
        print("updated portfolio")

    def update_from_fill(self):
        print("update from fill")

    @abstractmethod
    def check_signal(self):
        pass

class USBacktestPortfolio(BaseBacktestPortfolio):
    def check_signal(self):
        print("checked signal")

另请注意,您在抽象方法中不需要raise NotImplementedError。你可以只是pass。它更Pythonic :)


1
投票

当然,我可以忽略这一点,但完美的情况是,如果我能确保无法从BacktestPortfolio类中实例化对象。

你的例子就是这种情况:

>>> BaseBacktestPortfolio.mro()
[__main__.BaseBacktestPortfolio, __main__.Portfolio, abc.ABC, object]
>>> BaseBacktestPortfolio()
TypeError: Can't instantiate abstract class BaseBacktestPortfolio with abstract methods check_signal

由于ABCABCMeta只是常规类型,因此它们的特征是继承的。这包括他们防止实例化不完整的类。你的BaseBacktestPortfolio已经是一个抽象类。

来自IDE / linter / ...的警告专门用于警告您无法实例化BaseBacktestPortfolio

© www.soinside.com 2019 - 2024. All rights reserved.