gpt4 book ai didi

python - 为什么子类的实例化在 __init_subclass__ 内部工作,尽管它是一个缺少方法的抽象基类?

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

我正在尝试编写一个简单的插件系统。

a)为此,我使用 3.6 魔术函数 __init_subclass__ https://stackoverflow.com/a/41924331/1506569 找到了以下代码它改编自 PEP 487,在 plugins 列表中注册父类中定义的每个类。

b)我现在想“强制”插件的编写者实现一个特定的方法,该方法将由我的程序调用。理想情况下,这会在导入时警告用户,他的插件将无法工作,但不会阻止程序运行。为此,我尝试将 ABC 作为父类添加到插件中,并添加 @abstractmethod

我最初尝试使用 ABC 和 __init_subclass__:

from abc import ABC, abstractmethod

class Plugin(ABC):
plugins = []

@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
try:
__class__.plugins.append(cls()) # Does not raise exception
except Exception as e:
print("Warning: Your plugin might not work, missing abstract method")

@abstractmethod
def do_something(self):
...

class Render(Plugin):
def __init__(self):
print("Render init")

# does not implement 'do_something'

for plugin in Plugin.plugins:
plugin.do_something() # Calls 'do_something' on Render, without raising an exception

这里的问题是,实例化 __class__.plugins.append(cls()) 不会引发异常,而是将实例化的 Render 对象添加到插件列表。调用函数Render.do_something(底部的循环)也不会引发异常。它什么也不做。

我找到的解决方案描述如下:https://stackoverflow.com/a/54545842/1506569这只是比较基类和子类上的函数对象是否不同(通过使用 class 和 cls)。这使得从 ABC 继承变得不必要,而且看起来比需要的更复杂。

第二次尝试,没有 ABC:

class Plugin():
plugins = []

@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
if getattr(cls, 'do_something') is getattr(__class__, 'do_something'):
print("Warning: Your plugin might not work, missing 'do_something'")
else:
__class__.plugins.append(cls())

def do_something(self):
...

class Render(Plugin):
def __init__(self):
print("Render init")

for plugin in Plugin.plugins:
plugin.do_something()

这个版本可以工作,但对我来说似乎很复杂,看起来它可能会进一步崩溃?

有没有我错过的方法?为什么实例化有效?抱歉,如果我错过了类似的问题,我尝试搜索了很长时间。

最佳答案

如果你只是想强制子类实现一个方法,@abstractmethod就足够了。您不需要init_subclass。您的代码是正确的,但是,您尚未在任何地方实例化 Render。当创建对象时,抽象方法会给你一个错误,而不是类。如果你编写Render(),你实际上会得到一个错误

Can't instantiate abstract class Render with abstract methods do_something

关于python - 为什么子类的实例化在 __init_subclass__ 内部工作,尽管它是一个缺少方法的抽象基类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56358321/

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