【问题标题】:Can't set attributes on ElementTree.Element instance in Python 3无法在 Python 3 中的 ElementTree.Element 实例上设置属性
【发布时间】:2014-01-08 12:24:31
【问题描述】:

我不明白为什么在 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 类以某种棘手的方式实例化,但我不知道发生了什么。于是就有了这个问题。

【问题讨论】:

  • 我没有使用 python 3(仍在使用 2),但您可以尝试转储 t.__dict__ 并查看 foo 是否在其中?
  • 再次:请参阅我的答案中的第一个链接,并请检查返回的 python 3 对象是否具有 __dict__ 属性(并且可能等效地,如果它具有 __slots__ 属性)。使用__slots__ 会带来更好的内存性能,但有副作用,即您无法以正常方式添加属性(并且由于 etree [曾经] 是内存猪,这正是我希望他们做的) .如果它确实有槽,你只需要在你的对象中声明它们,为你想要的新字段声明一个__slots__,然后它就可以工作了。 (如果这是问题..)

标签: python elementtree


【解决方案1】:

这可能是故意的……看看Can't set attributes of object class。如果他们当时没有增强 ElementTree 以使用插槽而不是 dict,无论如何我都会感到惊讶。

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

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

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

2016 年 6 月 4 日更新:我的回答可能不清楚,但这是您可能需要做的事情(我通常是 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

【讨论】:

  • 查看我的问题的更新。我尝试在 python 对象上设置属性,而不是 XML 属性。我试图继承Element,这似乎不起作用。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    按照Python 3 documentation的说法,看来只能是现在了:

    >>> 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 下工作,但现在可能是强制性的。

    另外,an interesting ticket in Python bug tracker 他们决定更改异常消息。

    【讨论】:

      猜你喜欢
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多