Python 共享可变表的问题?
输出为:Python 共享可变表的问题?,python,Python,输出为: def set_if_not_there(d, fields, default_value=None): for field in fields: if not field in d: d[field] = default_value d = { } set_if_not_there(d, ['cnt1', 'cnt2'], 0) set_if_not_there(d, ['tags1', 'tags2'], []) d['cnt1
def set_if_not_there(d, fields, default_value=None):
for field in fields:
if not field in d:
d[field] = default_value
d = { }
set_if_not_there(d, ['cnt1', 'cnt2'], 0)
set_if_not_there(d, ['tags1', 'tags2'], [])
d['cnt1'] += 1
d['tags1'].append('work')
print d
正如您所看到的,tags1
和tags2
实际上引用的是同一个列表,这是不需要的cnt1
和cnt2
工作正常
如果不在那里,我如何实现
set\u
,以便仅在需要时创建可变表的副本
?也就是说,如果默认值是“标量”(int,string,None
,…),则不需要任何副本,但对于列表和dict,则需要副本。使用工厂函数而不是默认值:
{'tags2': ['work'], 'cnt2': 0, 'cnt1': 1, 'tags1': ['work']}
和传入可调用项(如函数、lambda或默认类型):
int()
返回0
,list()
返回一个新的空列表
例如,这也是标准库类型所做的
演示:
您只需要复制。deepcopy
>>> d = {}
>>> set_if_not_there(d, ['cnt1', 'cnt2'], int)
>>> set_if_not_there(d, ['tags1', 'tags2'], list)
>>> d['cnt1'] += 1
>>> d['tags1'].append('work')
>>> print d
{'tags2': [], 'cnt2': 0, 'cnt1': 1, 'tags1': ['work']}
结果:
import copy
def set_if_not_there(d, fields, default_value=None):
for field in fields:
if not field in d:
d[field] = copy.deepcopy(default_value)
d = { }
set_if_not_there(d, ['cnt1', 'cnt2'], 0)
set_if_not_there(d, ['tags1', 'tags2'], [])
d['cnt1'] += 1
d['tags1'].append('work')
print d
我认为我的方法更灵活,因为您可以定义默认值,而不仅仅是空值。如果您尝试:
>>>
{'tags2': [], 'cnt2': 0, 'cnt1': 1, 'tags1': ['work']}
您将获得:
set_if_not_there(d, ['cnt1', 'cnt2'], 0)
set_if_not_there(d, ['tags1', 'tags2'], [0,1])
d['cnt1'] += 1
d['tags1'].append('work')
print d
如果您确实希望避免导入**,可以尝试:
{'tags2': [0, 1], 'cnt2': 0, 'cnt1': 1, 'tags1': [0, 1, 'work']}
同样有效+1我需要将这种方法印在脑海中,因为它充满了优点!谢谢任何与
default\u factory=default\u factory或lambda:None
?如果不在那里(d,['cnt1',cnt2'],False)(您打算改为使用lambda:False
),则不会检测到类似set\u的错误。
set_if_not_there(d, ['cnt1', 'cnt2'], 0)
set_if_not_there(d, ['tags1', 'tags2'], [0,1])
d['cnt1'] += 1
d['tags1'].append('work')
print d
{'tags2': [0, 1], 'cnt2': 0, 'cnt1': 1, 'tags1': [0, 1, 'work']}
def set_if_not_there(d, fields, default_value=lambda:None):
for field in fields:
if not field in d:
d[field] = default_value()
d = { }
set_if_not_there(d, ['cnt1', 'cnt2'], lambda:0)
set_if_not_there(d, ['tags1', 'tags2'], lambda:[0,1])