gpt4 book ai didi

python - 为什么在元类派生自ABCMeta的类中需要使用@abstractmethod?

转载 作者:太空宇宙 更新时间:2023-11-03 11:45:20 24 4
gpt4 key购买 nike

PEP 3119指出:

The @abstractmethod decorator should only be used inside a class body, and only for classes whose metaclass is (derived from) ABCMeta. Dynamically adding abstract methods to a class, or attempting to modify the abstraction status of a method or class once it is created, are not supported.

但是,我找不到对为什么会这样的解释。具体来说,我没有注意到在未显式继承自 ABCMeta 的类中仅使用 @abstractmethod 时的行为差异。在下面这个简单的例子中,如果我理解正确的话,正确的做法是:

import six
from abc import ABCMeta
from abc import abstractmethod

class Base(six.with_metaclass(ABCMeta)):
def __init__(self):
print('Init abstract base')

@abstractmethod
def do_something(self):
pass

class Subclass(Base):
def __init__(self):
super(Subclass, self).__init__()

def do_something(self):
print('Done.')

sub = Subclass()
sub.do_something()

但是,如果我让 Base 类简​​单地从 object 继承,并且只在需要时使用装饰器,我注意到行为没有变化。

from abc import abstractmethod

class Base(object):
def __init__(self):
print('Init abstract base')

@abstractmethod
def do_something(self):
pass

class Subclass(Base):
def __init__(self):
super(Subclass, self).__init__()

def do_something(self):
print('Done.')

sub = Subclass()
sub.do_something()

我发现即使在更复杂的架构上也是如此,所以我想知道:后一种方法何时会失败?

最佳答案

您没有看到任何区别,因为您的第一个子类确实实现了 do_something 抽象方法。

注释掉两个版本子类中do_something的定义,你会发现第一种情况在尝试实例化子类时得到了一个TypeError - 你还会得到一个尝试实例化第一个版本 Base 类本身的 FWIW。使用第二个版本,您可以实例化这两个类(这不应该是可能的,因为它们是抽象的)并调用抽象的 do_something 方法——这违背了 ABC 的要点之一。

您还会错过 ABC FWIW 的许多其他有趣功能...

关于python - 为什么在元类派生自ABCMeta的类中需要使用@abstractmethod?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41163947/

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