为什么使用Abstract Base Class而不是使用NotImplemented方法的常规类?

时间:2016-10-04 16:02:31

标签: python-2.7 oop abstract-class

我在Python中使用了ABC来强制对特定接口进行编码。但是,我似乎只能通过创建一个方法未实现的类然后在实际实现中继承和覆盖来实现基本相同的事情。是否有更多的Pythonic理由为什么添加ABC,或者这只是为了使这种编码模式在语言中更加突出?

下面是我编写的代码片段,它实现了我的“NotImplemented”方案来定义抽象的“优化器”接口:

class AbstractOptimizer(object):
    '''
    Abstract class for building specialized optimizer objects for each use case.   
    Optimizer object will need to internally track previous results and other data so that it can determine the 
    truth value of  stopConditionMet(). 

    The constructor will require a reference argument to the useCaseObject, which will allow the optimizer
    to set itself up internally using fields from the use case as needed. There will need to be a close coupling between
    the optimizer code and the use case code, so it is recommended to place the optimizer class definition in the same module
    as the use case class definition.

    Interface includes a constructor and four public methods with no arguments: 

    0) AbstractOptimizer(useCaseObject) returns an instance of the optimizer
    1) getNextPoint() returns the current point to be evaluated 
    2) evaluatePoint(point) returns the modeling outputs "modelOutputs" evaluated at "point" 
    3) scorePoint(evaluationResults,metric) returns a scalar "score" for the results output by evaluatePoint according to metric. NOTE: Optimization is set up as a MINIMIZATION problem, so adjust metrics accordingly.
    4) stopConditionMet(score) returns True or False based on whatever past result are needed for this decision and the current score. If score = None, it is asumed to be the start of the optimization.
    5) getCurrentOptimalPoint() returns currently optimal point along with its iterationID and score

    The calling workflow will typically be: getNextPoint() -> evaluatePoint() -> scorePoint -> stopConiditionMet -> repeat or stop

    '''


    def __init__(self, useCaseObject):
        '''
        useCaseObject is a reference to use case instance associated with the optimizer.
        This optimizer will be "coupled" to this use case object.

        '''
        return NotImplemented

    def stopConditionMet(self,score = None):
        '''
        Returns True or False based on whether the optimization should continue.        
        '''
        return NotImplemented

    def getNextPoint(self):
        '''
        If stopConditionMet() evaluates to False, then getNextPoint() should return a point; otherwise, it should return None                
        '''
        return NotImplemented

    def evaluatePoint(self,point):
        '''
        Returns the modeling outputs "modelOutputs" evaluated at the current point.
        Will utilize the linked 
        '''
        return NotImplemented

    def scorePoint(self,evaluationResults,metric):
        '''
        Returns a scalar "score" for the current results evaluated in at the current point (from evaluatePoint) based on the function "metric"
        Note that "metric" will likely need to be a closure with the evaluation results as bound objects.
        '''
        return NotImplemented

    def getCurrentOptimum(self):
        '''
        returns currently optimal point and it's score as a dictionary: optimalPoint = {"point":point,"score":score}
        '''
        return NotImplemented

1 个答案:

答案 0 :(得分:0)

PEP 3119讨论了所有这些背后的理性

  

...此外,ABCs定义了一组最小的方法,用于建立类型的特征行为。根据ABC类型区分对象的代码可以相信这些方法将始终存在。这些方法中的每一个都伴随着广义的抽象语义定义,该定义在ABC的文档中描述。这些标准语义定义未强制执行,但强烈建议使用。

以上陈述似乎是一个重要的信息。 AbstractBaseClass提供标准object无法保证的保证。这些保证对于OOP风格开发的范例至关重要。特别是检查

  

另一方面,经典OOP理论家对检查的批评之一是缺乏形式主义和正在检查的内容的临时性质。在诸如Python之类的语言中,对象的几乎任何方面都可以被外部代码反射和直接访问,有许多不同的方法来测试对象是否符合特定协议。例如,如果问这个对象是一个可变序列容器吗?可以找到一个基类' list',或者可以找一个名为&#39的方法。 ;的的GetItem &#39 ;.但请注意,尽管这些测试看似显而易见,但它们都不正确,因为一个产生假阴性,另一个产生假阳性。

     

普遍认可的补救措施是使测试标准化,并将其分组为正式安排。通过将每个类与一组标准可测试属性相关联,可以通过继承机制或其他方式轻松完成。每个测试都带有一组promise:它包含关于类的一般行为的承诺,以及关于其他类方法可用的承诺。

     

本PEP提出了一种组织这些测试的特定策略,称为抽象基类(ABC)。 ABCs只是Python类,它们被添加到对象的继承树中,以向外部检查器发送该对象的某些特征。使用isinstance()进行测试,并且特定ABC的存在意味着测试已通过。

所以,虽然是的,你可以使用一个对象并模仿ABCMeta类的行为,ABC元类的重点是减少样板,误报,漏报,并提供关于代码的保证,否则将无法实现开发商,保证您没有繁重的工作。