gpt4 book ai didi

python - 定义抽象类的三种方式的区别

转载 作者:太空宇宙 更新时间:2023-11-03 13:59:54 32 4
gpt4 key购买 nike

我发现了多种(略有不同)的方法来在 Python 中定义抽象类。我阅读了文档,但在 stackoverflow 上也找不到答案。

这三个例子(见下面的代码)的主要区别是:

  • A 显式设置一个新的元类abc.ABCMeta
  • B 继承自 abc.ABC
  • C 继承自 objects 但定义了 @abc.abstractmethod

似乎 AB 没有区别(即 B 也有新的元类 abc.ABCMeta).但是,C 类仍然是 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("---")

最佳答案

abc.ABCMeta 类是实际执行abstractmethod 行为所必需的。它的目的是禁止实例化任何不实现抽象方法的类。装饰器本身不能强制执行,元类在实例化时强制执行装饰器:

class Foo:
@abstractmethod
def bar(self):
pass

Foo() # works

但是:

class Foo(metaclass=ABCMeta):
@abstractmethod
def bar(self):
pass

Foo()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: Can't instantiate abstract class Foo with abstract methods bar

因此,如果没有元类,abstractmethod 装饰器不会做任何事情。

abc.ABC 只是一个速记,因此您可以执行 Foo(ABC) 而不是 Foo(metaclass=ABCMeta),即全部:

A helper class that has ABCMeta as its metaclass. With this class, an abstract base class can be created by simply deriving from ABC avoiding sometimes confusing metaclass usage [..]

https://docs.python.org/3/library/abc.html#abc.ABC

关于python - 定义抽象类的三种方式的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50579029/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com