【问题标题】:Abstract methods in PythonPython中的抽象方法
【发布时间】:2011-08-16 22:48:39
【问题描述】:

我需要类似 Python (3.2) 中的 abstract protected 方法:

class Abstract:
    def use_concrete_implementation(self):
        print(self._concrete_method())

    def _concrete_method(self):
        raise NotImplementedError()


class Concrete(Abstract):
    def _concrete_method(self):
        return 2 * 3

定义一个“抽象”方法只是为了引发 NotImplementedError 真的有用吗?

在抽象方法中使用下划线是一种好的风格吗,在其他语言中是protected

抽象基类 (abc) 会改进什么吗?

【问题讨论】:

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


    【解决方案1】:

    在 Python 中,您通常会避免同时使用这些抽象方法。您通过文档定义一个接口,并简单地假设传入的对象满足该接口(“duck typing”)。

    如果你真的想用抽象方法定义一个抽象基类,这可以使用abc模块来完成:

    from abc import ABCMeta, abstractmethod
    
    class Abstract(metaclass=ABCMeta):
        def use_concrete_implementation(self):
            print(self._concrete_method())
    
        @abstractmethod
        def _concrete_method(self):
            pass
    
    class Concrete(Abstract):
        def _concrete_method(self):
            return 2 * 3
    

    同样,这不是 Python 的常用方式。 abc 模块的主要目标之一是引入一种重载 isinstance() 的机制,但通常避免 isinstance() 检查以支持鸭子类型。如果需要,请使用它,但不要作为定义接口的通用模式。

    【讨论】:

    • 这不是一个“pythonic 问题”。
    • 但是为什么不用代码本身“记录”并在“抽象”方法的主体中提出NotImplementedError
    • @deamon:如果你简单地省略这个方法,你会得到一个AttributeError。如果你实现它引发NotImplementedError,你会得到后一个异常。如果您觉得不同的错误消息值得额外的代码,那就去吧:) 我经常认为AttributeError 足够清晰,但在某些情况下您可能希望事情更加明确。
    • class Abstract(metaclass=ABCMeta) 仅适用于 Python 3,对吧?
    【解决方案2】:

    如有疑问,do as Guido does.

    没有下划线。只需将“抽象方法”定义为引发 NotImplementedError 的单行代码:

    class Abstract():
        def ConcreteMethod(self):
            raise NotImplementedError("error message")
    

    【讨论】:

    • ... 但 Guido 使用下划线表示抽象的“受保护”方法 ;-)
    • 你为什么要命名一个抽象方法Conrete
    • @Ethan Furman:因为期望程序员实现那个名字的方法。抽象类必须始终使用以后使用的名称来命名抽象方法。
    • @pepr:哦,对了——当我问这个问题时,我可以说真的很累吗?花园疲劳,也许吧? ;)
    【解决方案3】:

    基本上,这里不需要基类中的空方法。就这样做吧:

    class Abstract:
        def use_concrete_implementation(self):
            print(self._concrete_method())
    
    class Concrete(Abstract):
        def _concrete_method(self):
            return 2 * 3
    

    实际上,您通常甚至不需要 Python 中的基类。由于所有调用都是动态解析的,如果方法存在,则会调用它,如果不存在,则会引发AttributeError

    注意:在文档中提到_concrete_method需要在子类中实现是很重要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-21
      • 2014-07-09
      • 1970-01-01
      • 2022-11-22
      • 2022-06-25
      • 2012-09-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多