【问题标题】:Python Abstract class with concrete methods具有具体方法的 Python 抽象类
【发布时间】:2018-05-12 02:46:59
【问题描述】:

我想知道在 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. 如果是,那么声明类抽象是否总是有意义的,或者具体类是否可以具有抽象方法(在这种情况下,无论如何都不应该直接实例化它)。

谢谢

【问题讨论】:

标签: python class oop inheritance abstract-class


【解决方案1】:
  1. 根据the docs(括号中的文字和我的代码格式):

    [@abstractproperty is] 自 3.3 版起已弃用:现在可以将 property、property.getter()、property.setter() 和 property.deleter() 与 abstractmethod() 一起使用,从而使此装饰器变得多余。

    所以我认为你做得对。

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

  3. 我相信您仍然必须声明类抽象才能使用@abstractmethod 和类似的装饰器。通过将元类设置为 ABC,在定义所有抽象方法之前无法实例化该类,这听起来像您想要的行为,所以我认为您需要将其声明为抽象,除非您只想依靠文档来强制执行“您不应实例化”这个类的规则。顺便说一句,you can declare your abstract class with:

    from abc import ABC
    class MyBaseClass(ABC):
        # ...
    

    从abc 继承而不是手动设置元类。我认为这种结构是首选。

【讨论】:

    猜你喜欢
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    • 2019-11-19
    • 2011-01-08
    相关资源
    最近更新 更多