问题描述
以下代码有问题:
from lxml import etree as ET
class test(object):
def __init__(self,**args):
self.tag = []
self.meshfiles = []
self.root = None
def addMesh(self,**args):
if not "filename" in args:
raise KeyError("No filename given")
else:
self.meshfiles.append(args["filename"])
def populateTree(self,tag,text='',attr={},children={}):
return {'tag': tag,'text': text,'attr': attr,'children': children}
@property
def tree(self):
baum = {'meshes': {}}
if len(self.meshfiles) == 1:
baum['meshes'] = self.populateTree('mesh',text=self.meshfiles[0])
else:
baum['meshes'] = self.populateTree('meshes')
for i,meshfile in enumerate(self.meshfiles):
# works:
baum['meshes']['children'][i] = self.populateTree('mesh',text=meshfile)
# not working:
# baum['meshes']['children'][i] = self.populateTree('mesh',text=meshfile,children={})
return baum
def createXML(self):
self.root = ET.Element("rootelement")
self.dict2xml(self.root,self.tree)
return ET.tostring(self.root,pretty_print=True)
def dict2xml(self,parent,dictionary):
for entry in dictionary:
self.tag.append(ET.SubElement(parent,dictionary[entry]['tag']))
self.tag[-1].text = str(dictionary[entry]['text'])
for attr in dictionary[entry]['attr']:
self.tag[-1].set(attr,dictionary[entry]['attr'][attr])
if len(dictionary[entry]['children']) > 0:
self.dict2xml(self.tag[-1],dictionary[entry]['children'])
if __name__ == "__main__":
t = test()
t.addMesh(filename="a")
t.addMesh(filename="c")
t.addMesh(filename="b")
print(t.tree)
print(t.createXML())
虽然这个例子给出了递归错误:
{'meshes': {'tag': 'meshes','text': '','attr': {},'children': {0: {'tag': 'mesh','text': 'a','children': {...}},1: {'tag': 'mesh','text': 'c',2: {'tag': 'mesh','text': 'b','children': {...}}}}}
Traceback (most recent call last):
File "/home/buchwalj/temp/bug-python/test.py",line 48,in <module>
print(t.createXML())
File "/home/buchwalj/temp/bug-python/test.py",line 32,in createXML
self.dict2xml(self.root,self.tree)
File "/home/buchwalj/temp/bug-python/test.py",line 41,in dict2xml
self.dict2xml(self.tag[-1],dictionary[entry]['children'])
File "/home/buchwalj/temp/bug-python/test.py",dictionary[entry]['children'])
[PrevIoUs line repeated 994 more times]
File "/home/buchwalj/temp/bug-python/test.py",line 36,in dict2xml
self.tag.append(ET.SubElement(parent,dictionary[entry]['tag']))
RecursionError: maximum recursion depth exceeded while calling a Python object
注释掉第 27 行而不是第 25 行会打印出带有相应 xml 的正确字典。唯一的区别是,工作示例使用与函数调用中的默认参数相同的参数,而不是默认参数本身。 这是一个错误还是我在这里做错了什么?
解决方法
使用空字典作为默认值实际上是个坏主意,主要是因为字典是可变对象,这意味着如果您不小心更改了字典的内容,它会留在那里(因为对对象的引用保持不变)。请参阅:Why is the empty dictionary a dangerous default value in Python?
我建议将您的 populateTree
函数更改为:
def populateTree(self,tag,text='',attr=None,children=None):
if attr is None:
attr = {}
if children is None:
children = {}
return {'tag': tag,'text': text,'attr': attr,'children': children}
因此它创建了一个新的空字典,所有 populateTree
都在没有这些参数的情况下被调用。