无法在 Python 3 中的 ElementTree.Element 实例上设置属性



我不明白为什么在Python 3中我不能向ElementTree.Element实例添加一些属性。这是区别:

在 Python 2 中:

Python 2.6.6 (r266:84292, Jun 18 2012, 14:18:47) 
[GCC 4.4.6 20110731 (Red Hat 4.4.6-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from xml.etree import ElementTree as ET
>>> el = ET.Element('table')
>>> el.foo = 50
>>> el.foo
50
>>> 

在 Python 3 中:

Python 3.3.0 (default, Sep 11 2013, 16:29:08) 
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from xml.etree import ElementTree as ET
>>> el = ET.Element('table')
>>> el.foo = 50
>>> el.foo
AttributeError: foo
>>> 

Python 2 由发行版 (CentOS) 提供。Python 3 是从源代码编译的。

这是预期的行为、错误,还是我必须使用一些额外的标志重新编译 python 3?

更新:

一些澄清:我正在尝试在 Python 对象上设置属性,即在实例上设置Element属性。不是 XML 属性 ( Element.attrib )。

当我尝试对Element进行子类化时,实际上出现了这个问题。下面是示例:

>>> class Table(ET.Element):
...     def __init__(self):
...         super().__init__('table')
...         print('calling __init__')
...         self.foo = 50
... 
>>> t = Table()
calling __init__
>>> t.foo
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'Table' object has no attribute 'foo'
>>> 

这让我认为Element类是以某种棘手的方式实例化的,但我无法弄清楚发生了什么。因此问题来了。

这可能是故意的...看看不能设置对象类的属性。如果他们当时没有增强 ElementTree 以使用插槽而不是字典,无论如何我都会感到惊讶。

不清楚你想做什么......你真的在尝试设置 python 属性还是 XML 属性?如果是后者,你真的想这样做:

el = ET.Element('table')
el.set('foo', 50) 
#or
el.attrib['foo'] = 50

如果你真的想添加python属性,你应该改用子类,并且可能提供你自己的Element/SubElement函数来提供"包装"元素而不是标准元素。

更新 6/4/2016:也许从我的回答中不清楚,但这是您可能需要做的(我通常是 python 2.7):

class Table(ET.Element):
    # Adding __slots__ gives it a known attribute to use    
    __slots__ = ('foo',)
    def __init__(self):
        super().__init__('table')
        print('calling __init__')
        self.foo = 50

由于 3.3 ElementTree 尝试导入 c 实现以提高效率,但是您不能在该实现上设置任意属性。 如果您不想每次都使用 Set 或 Get 方法,则应使用 ET._Element_Py,即 Python 实现。

根据 Python 3 文档,似乎唯一的方法就是现在:

>>> from xml.etree import ElementTree as ET
>>> el = ET.Element('table')
>>> el.set("foo", 50)
>>> el.get("foo")
50
>>> el.attrib
{"foo": 50}

它在Python 2.X下也可以工作,但现在可能是强制性的。

此外,Python 错误跟踪器中有一个有趣的票证,他们决定更改异常消息。

最新更新