1

I have a Python class for a Person object which inherits xml.etree.ElementTree.Element.

from xml.etree import ElementTree
class Person(ElementTree.Element):
    def __init__(self, name, age):
        super().__init__("person", name=name, age=str(age))

person = Person("Paul", 23)

I plan on expanding my Person class to include additional attributes and subtags. Before doing this, I want to simplify attribute access by converting my class to use lxml.objectify.Element.

from lxml import objectify
class Person(objectify.Element):
    def __init__(self, name, age):
        super().__init__("person", name=name, age=str(age))

person = Person("Paul", 23)

Unfortunately, trying to inherit from objectify.Element raises a TypeError about creating cython_function_or_method instances.

Traceback (most recent call last):
  File "C:/Users/svascellar/.PyCharmCE2017.3/config/scratches/scratch_1.py", line 2, in <module>
    class Person(objectify.Element):
TypeError: cannot create 'cython_function_or_method' instances

Why is my class raising a TypeError? How do I inherit frrom lxml.objectify.Element?

4

1 回答 1

2

事后看来,我建议不要使用lxml来创建子类。

正如评论中提到的,lxml.objectify.Element()不是一个类。它是一种创建并返回对象的工厂方法,这意味着它不能被继承。

虽然可以从ElementBaseor继承ObjectifiedElement,但 lxml 文档强烈警告您不能覆盖__init__or __new__,我的原始答案就是这样做的。

BIG FAT WARNING:子类不能覆盖__init__,或者__new__当这些对象将被创建或销毁时它是绝对未定义的。元素的所有持久状态都必须存储在底层 XML 中。如果确实需要在创建后初始化对象,可以实现一个 _init(self) 方法,该方法会在对象创建后直接调用。
-文档lxml.etree.ElementBase

我建议改为从不同的类继承。lxml.etree.ElementTree.Element如原始问题中所述,您可以很容易地继承。

from xml.etree import ElementTree
class Person(ElementTree.Element):
    def __init__(self, name, age):
        super().__init__("person", name=name, age=str(age))

person = Person("Paul", 23)

使用的子类lxml可能比它的价值更麻烦。但是,如果您真的想在lxml有警告的情况下进行子类化,您可以在下面看到我的原始答案。


旧答案(不安全)

尝试从继承lxml.objectify.ObjectifiedElement

from lxml import objectify
class person(objectify.ObjectifiedElement):
    def __init__(self, name, age):
        super().__init__(name=name, age=str(age))

my_person = person("Paul", 23)
print(etree.tostring(my_person, encoding="unicode"))
# output: <person age="23" name="Paul"/>

确保您的类名与您的 XML 标记匹配,因为ObjectifiedElement根 XML 标记名使用类名。

正如Goyobruno desthuilliers指出的那样,objectify.Element它不是一个类,这意味着你不能从它继承。离开他们的评论,我曾经type()为自己确认这一点,发现objectify.Element()返回了一个类型的对象ObjectifiedElement

from lxml import objectify
person = objectify.Element("person", name="Paul", age="23")
print(type(person))
# output: <class 'lxml.objectify.ObjectifiedElement'>

将我的类更改为继承自lxml.objectify.ObjectifiedElement后,该类按预期工作。

于 2018-03-19T15:41:50.923 回答