正确的方法来实现ABC SubClass

时间:2018-06-15 10:37:31

标签: python python-3.x abstract-class

我有一个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类中实例化一个对象。

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

您可以将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。你可以require_once __DIR__ . '/vendor/autoload.php'; /** * Minimal options */ $options = array( \WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_URL => 'http://www.gls-group.eu/276-I-PORTAL-WEBSERVICE/services/ParcelShopSearch/wsdl/2010_01_ParcelShopSearch.wsdl', \WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_TRACE => true, \WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_CLASSMAP => ClassMap::get(), \WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_LOGIN => 'mylog', \WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_PASSWORD => 'mypass', ); $id = "2500686161"; /** * Samples for Get ServiceType */ $get = new \ServiceType\Get($options); /** * Sample call for GetParcelShopById operation/method */ if ($get->GetParcelShopById(new \StructType\GetParcelShopByIdRequestType($id)) !== false) { print_r($get->getResult()); } else { print_r($get->getLastError()); } 。它更Pythonic:)