Woj*_*ilo 5 python abstract-class introspection python-3.x
我正在编写一个插件框架,我希望能够编写一个装饰器interface,它将用户类转换为 ABC 类并用抽象方法替换所有方法。我无法让它工作,我想问题与错误的 mro 有关,但我可能是错的。
我基本上需要写:
@interface
class X:
def test(self):
pass
x = X() # should fail, because test will be abstract method.
Run Code Online (Sandbox Code Playgroud)
用它们的抽象版本替换方法很简单(你必须迭代 func 并将它们替换为abc.abstractmethod(func)),但是我在创建动态类型时遇到了问题,这将是一个ABCmeta元类。
现在我有类似的东西:
from abc import ABCMeta
class Interface(metaclass=ABCMeta):
pass
def interface(cls):
newcls = type(cls.__name__, (Interface, cls), {})
# substitute all methods with abstract ones
for name, func in inspect.getmembers(newcls, predicate=inspect.isfunction):
setattr(newcls, name, abstractmethod(func))
return newcls
Run Code Online (Sandbox Code Playgroud)
但它不起作用 - 我可以毫无错误地初始化类 X。
使用 Python 中 ABC 的标准用法,我们可以这样写:
class X(metaclass=ABCMeta):
@abstractmethod
def test(self):
pass
x = X() # it will fail
Run Code Online (Sandbox Code Playgroud)
如何在 Python3 中创建动态类型,它的行为就像它有元类一样,并将ABCmeta用抽象函数替换所有函数?
诀窍是不使用setattr重置每个属性,但代替的那些修改的属性传递给type功能作为字典:
import inspect
from abc import ABCMeta, abstractmethod
class Interface(metaclass=ABCMeta):
pass
def interface(cls):
attrs = {n: abstractmethod(f)
for n, f in inspect.getmembers(cls, predicate=inspect.isfunction)}
return type(cls.__name__, (Interface, cls), attrs)
@interface
class X(metaclass=ABCMeta):
def test(self):
pass
x = X()
# does fail:
# Traceback (most recent call last):
# File "test.py", line 19, in <module>
# x = X() # should fail, because test will be abstract method.
# TypeError: Can't instantiate abstract class X with abstract methods test
Run Code Online (Sandbox Code Playgroud)