I'm using Python 3.6.5. What works:
from xml.etree.ElementTree import Element, SubElement
root = Element("root")
SubElement(root, "sub")
what doesn't:
from xml.etree.ElementTree import Element, SubElement
root = Element("root")
SubElement(parent=root, tag="sub")
So the only difference is passing parent
and tag
as keyword arguments (with proper keywords, mind you). Also look at the stack trace:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: SubElement() takes at least 2 arguments (0 given)
How on Earth there were 0 arguments given?
A look at the source for SubElement
: lines 443:459 hasn't struck me with any revelations. As you can see the two positional parameters of SubElement
are indeed named parent
and tag
.
Are we to have second thoughts about validity of this particular Raymond Hettinger's piece of advice?
The reason of that behavior can be found at the end of ElementTree.py
:
# Import the C accelerators
try:
# Element is going to be shadowed by the C implementation. We need to keep
# the Python version of it accessible for some "creative" by external code
# (see tests)
_Element_Py = Element
# Element, SubElement, ParseError, TreeBuilder, XMLParser
from _elementtree import *
except ImportError:
pass
The Python code you can read (def SubElement(parent, tag, attrib={}, **extra)
) is NOT the one that will be used when you call SubElement()
from your own code. Instead, a more efficient version, written in C and compiled for your OS, will be used. This ensure better performances of the library.
As a result, some syntaxic sugar usually available in Python (ability to choose between named arguments or positional ones) may not be available.