Xia*_*nni 3 python abstract-class python-3.x
我在网上看代码的时候,遇到过以下使用抽象类的情况:
from abc import abstractmethod,ABCMeta
class Generator(object,metaclass=ABCMeta):
@abstractmethod
def generate(self):
raise NotImplementedError("method not implemented")
generator=Generator()
generator.generate()
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,返回以下错误:
TypeError: Can't instantiate abstract class Generator with abstract methods generate
但如果我这样写(唯一的区别在第二行)
from abc import abstractmethod,ABCMeta
class Generator(object):
@abstractmethod
def generate(self):
raise NotImplementedError("method not implemented")
generator=Generator()
generator.generate()
Run Code Online (Sandbox Code Playgroud)
虽然错误信息有变化,
NotImplementedError: method not implemented
当我实现该generate方法时,上述两种方式都Generator正确执行,
class GeneticAlgorithm(Generator):
def generate(self):
print("ABC")
ga=GeneticAlgorithm()
ga.generate()
Run Code Online (Sandbox Code Playgroud)
>>> ABC
Run Code Online (Sandbox Code Playgroud)
那么为什么我们需要声明呢metaclass=ABCMeta?
我从GeeksforGeeks了解到一些事情
ABCMeta 元类提供了一个称为 register 方法的方法,可以由其实例调用。通过使用此注册方法,任何抽象基类都可以成为任何任意具体类的祖先。
但这还是没有让我明白声明的必要性metaclass=ABCMeta,感觉@abstractmethod修改一下方法就够了。
您“需要”在实例化时metaclass=ABCMeta强制执行规则。
generator=Generator() # Errors immediately when using ABCMeta
generator.generate() # Only errors if and when you call generate otherwise
Run Code Online (Sandbox Code Playgroud)
想象一下,如果该类有多个抽象方法,但只有其中一些在子类中实现。它可能会工作很长一段时间,并且只有当您调用未实现的方法时才会出错。在依赖 ABC 之前急切地失败通常是一件好事,同样,函数引发异常通常比仅仅返回None来指示失败更好;您希望在出现问题时立即知道,而不是在不知道错误的最终原因的情况下出现奇怪的错误。
旁注:有一种比明确使用metaclass=ABCMeta语法更简洁的方法来成为 ABC:
from abc import abstractmethod, ABC
class Generator(ABC):
Run Code Online (Sandbox Code Playgroud)
Python 几乎总是创建使用元类的空基类来简化使用(特别是在 2 到 3 过渡期间,没有兼容的元类语法可以在两者中使用,直接继承是唯一有效的方法)。