Python Abstract类具体方法

时间:2017-11-28 15:23:10

标签: python class oop inheritance abstract-class

我想知道在python(3)中抽象类是否可以有具体的方法 虽然这似乎有效,但我不确定这是在python中执行此操作的正确方法:

from abc import ABCMeta, abstractclassmethod, abstractmethod 

class MyBaseClass:
    __metaclass__ = ABCMeta

    @property
    @abstractmethod
    def foo_prop(self):
        """Define me"""
        pass

    @abstractclassmethod
    def get_something(cls, param1, param2, param3):
        """This is a class method, override it with @classmethod """
        pass

    @classmethod
    def get(cls, param1, param2):
        """Concrete method calling an abstract class method and an abstract property""" 
        if param1 < cls.foo_prop:
            raise Exception()
        param3 = param1 + 42
        item = cls.get_something(param1, param2, param3)
        return item


class MyConcreteClassA(MyBaseClass):
    """Implementation """

    foo_prop = 99

    @classmethod
    def get_something(cls, param1, param2, param3):
        return cls.foo_prop + param1 + param2 + param3


class MyConcreteClassB(MyBaseClass):
    """Implementation """

    foo_prop = 255

    @classmethod
    def get_something(cls, param1, param2, param3):
        return cls.foo_prop - param1 - param2 - param3

在示例中,抽象类MyBaseClass具有:

  • 将在子类中定义的抽象属性foo_prop
    • 我能找到宣告这个的唯一方法是创建一个抽象的“属性方法”
  • 将在子类中实现的抽象类方法get_something
  • 一个具体的方法get,它依次使用上面提到的(尚未定义的)抽象方法和属性。

问题

  1. 有没有更好的方法来定义抽象属性?将MyBaseClass中的具体属性设置为None并在子类中重新定义它会更有意义吗?

  2. 我可以在抽象类中混合抽象和具体方法,如示例所示吗?

  3. 如果是,那么声明类抽象或者具体类是否具有抽象方法总是有意义的(在这种情况下,它永远不应该直接实例化)。

  4. 由于

1 个答案:

答案 0 :(得分:2)

  1. 根据the docs(括号中的文字和我的代码格式):

      

    [@abstractproperty是]从版本3.3开始不推荐使用:现在可以将propertyproperty.getter()property.setter()property.deleter()与{{1}一起使用,使这个装饰者多余。

    所以我认为你做得对。

  2. 你可以这样做,或者至少根据我的经验,这不是问题。也许其他人可以提供其他建议,但这个建议可能采取的形式是&#34;继承是坏的&#34;。虽然我在文档中没有明确地看到任何内容,this section shows an example其中抽象方法,具体方法和类方法都在ABC中定义。

  3. 我相信您仍然必须声明类抽象才能使用abstractmethod()和类似的装饰器。通过将元类设置为ABC,在定义所有抽象方法之前无法实例化类,这听起来像您想要的行为,所以我认为您需要将其声明为抽象,除非您只是想依靠文档来强制执行&# 34;你不应该实例化#34;关于这门课的规则。另外,you can declare your abstract class with

    @abstractmethod

    继承自from abc import ABC class MyBaseClass(ABC): # ... 而不是手动设置元类。我认为这种结构是首选。