python - 用于创建字典的函数中的默认参数会创建一个无限循环的自引用
问题描述
a 使用以下代码遇到以下问题:
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', 'attr': {}, 'children': {...}}, 1: {'tag': 'mesh', 'text': 'c', 'attr': {}, 'children': {...}}, 2: {'tag': 'mesh', 'text': 'b', 'attr': {}, '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", line 41, in dict2xml
self.dict2xml(self.tag[-1], dictionary[entry]['children'])
File "/home/buchwalj/temp/bug-python/test.py", line 41, in dict2xml
self.dict2xml(self.tag[-1], 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 的正确字典。唯一的区别是,工作示例使用与函数调用中的默认参数相同的参数,而不是默认参数本身。这是一个错误还是我在这里做错了什么?
解决方案
使用空字典作为默认值实际上是个坏主意,主要是因为字典是可变对象,这意味着如果您不小心更改了字典的内容,它就会保留下来(因为对对象的引用保持不变)。请参阅:为什么空字典在 Python 中是一个危险的默认值?
I would suggest changing your populateTree
function to something like:
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}
so it creates a new empty dictionary everything populateTree
is called without those arguments.
推荐阅读
- reactjs - GraphQL(Prisma)突变数据未定义
- npm - 无法构建大型机操作系统开发应用程序
- nlp - 如何训练会导致两个新闻标题之间的相似度得分的模型?
- java - getname() 和 addmemberlist() 的问题
- django - 试图显示最新记录 - Django
- python-3.x - 如何加快 featuretools dfs 的执行速度?
- python - Python:解析 JSON 密钥错误
- python - 如何创建重复字符串的动态大小列并将其同时添加到数据框中
- python - Sentry 没有从 localhost 收到错误(本地)
- c++ - 如何包含 a.dll 描述/公司信息?