具有具体方法的Python抽象类

2024-09-28 22:19:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道在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
    • 我能找到的唯一方法就是创建一个抽象的“property方法”
  • 将在子类中实现的抽象类方法get_something
  • 一个具体的方法get,它反过来使用上面提到的(尚未定义的)抽象方法和属性。在

问题

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

  2. 我可以在一个抽象类中混合抽象方法和具体方法吗?

  3. 如果是,那么声明抽象类总是有意义的,还是一个具体的类有抽象的方法(在这种情况下,无论如何都不应该直接实例化它)。

谢谢


Tags: 方法get定义foodef抽象类somethingclass
1条回答
网友
1楼 · 发布于 2024-09-28 22:19:12
  1. 根据the docs(括号内的文本和我的代码格式):

    [@abstractproperty is] Deprecated since version 3.3: It is now possible to use property, property.getter(), property.setter() and property.deleter() with abstractmethod(), making this decorator redundant.

    所以我觉得你做得对。

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

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

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

    继承自abc,而不是手动设置元类。我认为这种结构是最好的。

相关问题 更多 >