no_*_*123 3 python abstract-class python-3.x
我发现了多种(略有不同)在Python中定义抽象类的方法。我阅读了文档,但在stackoverflow上也找不到答案。
这三个示例之间的主要区别(请参见下面的代码)是:
Aabc.ABCMeta显式设置新的元类B 继承自 abc.ABCC继承objects但定义@abc.abstractmethod类似乎A和B没什么不同(即也B有新的metaclass abc.ABCMeta)。但是,类C仍然是type type。
不为其定义元类有C什么影响?什么时候需要定义元类,或者不abc.ABCMeta为抽象类定义元类是错误/不好的风格?但是,该班级的C表现似乎符合我对ABC的期望。
import abc
class A(metaclass=abc.ABCMeta):
# Alternatively put __metaclass__ = abc.ABCMeta here
@abc.abstractmethod
def foo(self):
raise NotImplementedError
class B(abc.ABC):
@abc.abstractmethod
def foo(self):
raise NotImplementedError
class C(object):
@abc.abstractmethod
def foo(self):
raise NotImplementedError
class Aimpl(A):
def foo(self):
print("Aimpl")
class Bimpl(B):
def foo(self):
print("Bimpl")
class Cimpl(C):
#def foo(self):
# print("Cimpl")
pass
Aimpl().foo() # Aimpl
print(isinstance(Aimpl, A)) # False
print(issubclass(Aimpl, A)) # True
print(isinstance(Aimpl, abc.ABCMeta)) # True
print(type(A)) # <class 'abc.ABCMeta'>
print("---")
Bimpl().foo() # Bimpl
print(isinstance(Bimpl, B)) # False
print(issubclass(Bimpl, B)) # True
print(isinstance(Bimpl, abc.ABCMeta)) # True
print(type(B)) # <class 'abc.ABCMeta'>
print("---")
Cimpl().foo() # Cimpl
print(isinstance(Cimpl, C)) # False
print(issubclass(Cimpl, C)) # True
print(isinstance(Cimpl, abc.ABCMeta)) # False
print(type(C)) # <class 'type'>
print("---")
Run Code Online (Sandbox Code Playgroud)
该abc.ABCMeta班是需要实际执行abstractmethod的行为。其目的是禁止实例化未实现abstract方法的任何类。装饰器本身不能强制执行该操作,元类在实例化时强制装饰器:
class Foo:
@abstractmethod
def bar(self):
pass
Foo() # works
Run Code Online (Sandbox Code Playgroud)
然而:
class Foo(metaclass=ABCMeta):
@abstractmethod
def bar(self):
pass
Foo()
Run Code Online (Sandbox Code Playgroud)
class Foo:
@abstractmethod
def bar(self):
pass
Foo() # works
Run Code Online (Sandbox Code Playgroud)
因此,没有元类,abstractmethod装饰器就什么也不做。
abc.ABC只是一个简写,所以您可以Foo(ABC)代替,仅此而已Foo(metaclass=ABCMeta):
具有
ABCMeta作为其元类的帮助程序类。使用此类,可以通过ABC避免有时混淆元类用法的简单派生来创建抽象基类[..]