我正在编写装饰代码(出于好奇的缘故),以便在python中创建类抽象。到目前为止,它似乎可以正常工作,但是我出现了意外的行为。
装饰的主意如下所示:
from abc import ABCMeta, abstractmethod
def abstract(cls):
cls.__metaclass__ = ABCMeta
return cls
然后,在使用这种装饰时,只需定义一个抽象方法
@abstract
class Dog(object):
@abstractmethod
def bark(self):
pass
但是当我测试时,我可以实例化Dog对象:
d = Dog()
d.bark() //no errors
Dog.__metaclass__ //returned "<class 'abc.ABCMeta'>"
当测试直接分配
__metaclass__
时,它的行为符合预期:class Dog(object):
__metaclass__ = ABCMeta
@abstractmethod
def bark(self):
pass
测试:
d = Dog()
"Traceback (most recent call last):
File "<pyshell#98>", line 1, in <module>
d = Dog()
TypeError: Can't instantiate abstract class Dog with abstract methods bark"
为什么会这样呢?
最佳答案
我已经能够重现您的问题。
ABCMeta .__ new__从未使用您的装饰器称为。当您将其真正定义为Dog的元类时,它就会被调用。这是因为已经定义了Dog类,因此在之后添加ABCMeta实际上没有任何区别,因为在定义时未调用其新,不会将Dog类注册为抽象类,也不会发现它的抽象方法。我邀请您阅读ABCMeta。 新的代码,您将看到它的作用。
但是,我找到了这个解决方案,仍然可以使装饰器正常工作:
def abstract(cls):
return ABCMeta(cls.__name__, cls.__bases__, dict(cls.__dict__))
现在可以正常工作了。这意味着必须子类
Dog
才能调用bark
。关于python - Python抽象装饰不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32640184/