Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中将通用方法放在抽象类中是一种好的做法吗?_Python_Inheritance_Abstract Class - Fatal编程技术网

在Python中将通用方法放在抽象类中是一种好的做法吗?

在Python中将通用方法放在抽象类中是一种好的做法吗?,python,inheritance,abstract-class,Python,Inheritance,Abstract Class,我使用这个模块来定义子类必须支持的接口。还有一些常见的方法存在于所有子类中。把它们放在抽象类中可以吗,还是应该只包含抽象方法(即用@abc.abstractmethod修饰)?TL;博士是的,抽象类可以有非抽象方法 通常我们所说的抽象类只是一个无法实例化的类 另一方面,我们所称的接口是一个只有方法声明但没有实现的类。特别是它是一个抽象类,因为它没有构造函数 当然,在Python中没有真正的接口:每个方法都必须有一个主体。但是我们可以通过raisenotimplementederror()模拟接口

我使用这个模块来定义子类必须支持的接口。还有一些常见的方法存在于所有子类中。把它们放在抽象类中可以吗,还是应该只包含抽象方法(即用
@abc.abstractmethod
修饰)?

TL;博士是的,抽象类可以有非抽象方法

通常我们所说的抽象类只是一个无法实例化的类

另一方面,我们所称的接口是一个只有方法声明但没有实现的类。特别是它是一个抽象类,因为它没有构造函数

当然,在Python中没有真正的接口:每个方法都必须有一个主体。但是我们可以通过
raisenotimplementederror()
模拟接口

无论如何,接口构成了抽象类的子集。这显然表明存在不是接口的抽象类。这正是你所描述的情况。是的,抽象类可能包含实现的非抽象方法。这是一个不错的做法。当给定的方法不依赖于具体的实现时,这尤其有用


例如,考虑一个泛型解析器的接口(我正在考虑<代码> JSON.Load 和<代码> JSON. Load ):

loads
方法一个默认实现,它接受一个字符串而不是流,这是完全可以的:

class AbstractLoader(ABC):
    @abstractmethod
    def load(self, stream):
        raise NotImplementedError()

    def loads(self, text):
        stream = io.StringIO(text)
        return self.load(stream)

虽然我会使用
Abstract
前缀而不是
I
;)

通常,接口和抽象类之间的区别在于接口没有字段,也没有实现任何方法。根据上下文,这两个概念都很有用。然而,在Python中没有明确的区别。但是在抽象类中实现方法没有什么错。这样做比使用
raise NotImplementedError
有什么好处吗?@RockyLi是的,从抽象类继承的类必须实现其所有的抽象方法。绕过这个要求很简单(
abc
是一个库,而不是语言功能),但它仍然是很好的文档,也是防止忘记实现抽象方法的第一道防线。此外,将所有子类都应该访问的通用方法放在基类中是标准的OO实践,与基类是否抽象无关
class AbstractLoader(ABC):
    @abstractmethod
    def load(self, stream):
        raise NotImplementedError()

    def loads(self, text):
        stream = io.StringIO(text)
        return self.load(stream)