【发布时间】:2018-12-13 13:32:24
【问题描述】:
我想实现一个元类来包装方法来记录附加信息。但我还需要abstractmethods。我试图扩展 ABCMeta 但它似乎没有强制执行 @abstractmethod 装饰器:
import types
import abc
def logfunc(fn, *args, **kwargs):
def fncomposite(*args, **kwargs):
rt = fn(*args, **kwargs)
print("Executed %s" % fn.__name__)
return rt
return fncomposite
class LoggerMeta(abc.ABCMeta):
def __new__(cls, clsname, bases, dct):
for name, value in dct.items():
if type(value) is types.FunctionType or type(value) is types.MethodType:
dct[name] = logfunc(value)
return super(LoggerMeta, cls).__new__(cls, clsname, bases, dct)
def __init__(cls, *args, **kwargs):
super(LoggerMeta, cls).__init__(*args, **kwargs)
if cls.__abstractmethods__:
raise TypeError("{} has not implemented abstract methods {}".format(
cls.__name__, ", ".join(cls.__abstractmethods__)))
class Foo(metaclass=LoggerMeta):
@abc.abstractmethod
def foo(self):
pass
class FooImpl(Foo):
def a(self):
pass
v = FooImpl()
v.foo()
当我运行它时,它会打印出Executed foo。但是我预计它会失败,因为我没有在FooImpl 中实现foo。
我该如何解决这个问题?
【问题讨论】:
-
嗯...您在元类
__new__中用非抽象函数装饰(替换)了您的抽象方法。你期待什么? -
您只能装饰非抽象成员。那应该可以。
-
好吧,我也认为是这样。但我也希望记录抽象成员。猜猜我不熟悉 ABCMeta 是如何实现的。我认为只要我们不更改函数名称,当涉及到抽象方法检查时,它指向哪个实际函数并不重要。
标签: python python-3.x metaprogramming metaclass abstract-methods