我试图用一个抽象方法(addfeature)来实现一个抽象超类(Base),Child类将覆盖它.
from lxml.builder import ElementMaker
from abc import ABCMeta, abstractmethod
class Base(object):
__metaclass__ = ABCMeta
ns = "http://www.foo.com/bar"
em = ElementMaker(namespace=ns, nsmap={'bar': ns})
@abstractmethod
def addfeature(self):
pass
class Child(Base):
def addfeature(self):
pass
child_instance = Child()
这段代码失败,但是
“TypeError: Can’t instantiate abstract class Child with abstract
methods em”
为什么? em应该是类属性,而不是方法(当然也不是抽象方法)
解决方法:
ABCMeta使用__isabstractmethod__属性检查该方法是否抽象. lxml.builder.ElementMaker动态生成一个方法(使用__getattr__
);访问__isabstractmethod__会混淆ABCMeta.
>>> ns = "http://www.foo.com/bar"
>>> em = ElementMaker(namespace=ns, nsmap={'bar': ns})
>>> em.child_element
<functools.partial object at 0x0000000002B55598>
>>> em.child_element()
<Element {http://www.foo.com/bar}child_element at 0x27a8828>
>>> em.__isabstractmethod__
<functools.partial object at 0x0000000002B55598>
>>> bool(em.__isabstractmethod__)
True
通过将__isabstractmethod__分配为False,可以解决该问题.
class Base(object):
__metaclass__ = ABCMeta
ns = "http://www.foo.com/bar"
em = ElementMaker(namespace=ns, nsmap={'bar': ns})
em.__isabstractmethod__ = False # <-----
@abstractmethod
def addfeature(self):
pass