Python:如何在单表达式中深层添加到字典?
我想知道,如何在一个表达式中,得到一个字典,其中一个键值对被添加到某个输入字典的子字典里?而且输入字典要保持不变。可以假设这个子字典是存在的,并且新的键值对在子字典中还不存在。
更新 2(下面会解释"SOsurvivalConditions"等的定义):
最简洁的方法是:
(SOsurvivalConditions['firstCondition'].setdefault('synonym', 'A modern form of RTFM is: Google It.'), SOsurvivalConditions)[-1]
更新 1:
这个方法满足了要求,并且不会修改输入字典:
dict((k,dict(v, synonym='A modern form of RTFM is: Google It.') if k == "firstCondition" else v) for k,v in SOsurvivalConditions.iteritems())
不过,更简洁(但只是语句)的方式可以通过一个辅助函数来实现,例如:
import copy
def dictDeepAdd(inputDict, dictKey, newKey, newValue):
"""
Adds new key-value pair to a sub-dictionary and
returns a new version of inputDict.
dictKey is the key in inputDict for which a new
key-value pair is added.
Side-effect: none (does not change inputDict).
"""
toReturn = copy.deepcopy(inputDict)
toReturn[dictKey][newKey] = newValue
return toReturn
dictDeepAdd(
SOsurvivalConditions,
'firstCondition',
'synonym',
'A modern form of RTFM is: Google It.'
)
示例:
goodStyle = \
{
'answer': 'RTFM responses are not acceptable on Stack Overflow - Joel Spolsky has repeatedly said so in the Stack Overflow podcasts.',
'RTFM' : 'RTFM is, in the less offensive version, an abbreviation for Read The Fine Manual.',
}
SOsurvivalConditions = \
{
'moodImperative' : 'be happy',
'firstCondition' : goodStyle,
}
'firstCondition'在SOsurvivalConditions中现在有两个键值对。需要添加一个新的键值对,('synonym', '现代版的RTFM是:谷歌一下。'),并且结果应该在一个表达式中可用。
这个方法有效(虽然这里分成了几行,但实际上是一行):
{
'moodImperative': SOsurvivalConditions['moodImperative'],
'firstCondition' :
dict(
SOsurvivalConditions['firstCondition'],
synonym = 'A modern form of RTFM is: Google It.'
)
}
并返回:
{'moodImperative': 'be happy',
'firstCondition':
{'answer': 'RTFM responses are not acceptable on Stack Overflow - Joel Spolsky has repeatedly said so in the Stack Overflow podcasts.',
'RTFM': 'RTFM is, in the less offensive version, an abbreviation for Read The Fine Manual.',
'synonym': 'A modern form of RTFM is: Google It.'
}
}
不过这个表达式中有很多重复的部分——所有的键都重复了。而'firstCondition'出现了两次。有没有更优雅的方法呢?
(这里的数据结构的名称和内容是虚构的,但代表了我今天遇到的一个真实问题。Python版本:2.6.2。)
6 个回答
你是在寻找 dict.update
的用法吗?相关的文档可以在这里找到。
SOsurvivalConditions['firstCondition'].update({'synonym': 'A modern form of RTFM is: Google It.'})
我觉得这就是你想要的内容。
这里有一个满足你特殊要求的例子(在你描述的模糊范围内):
(SOsurvivalConditions['firstCondition'].setdefault('synonym', 'A modern form of RTM is: Google It.'), SOsurvivalConditions)[-1]
这个例子会修改最初的数据结构(而不是像@truppo的回答那样创建新的结构),而且它是一个表达式,会返回整个字典(而不是像@Evan的回答那样是一个语句,或者像@Seth的回答那样返回None)。
当然,很多不同的变体都是可能的(如果你希望新的条目覆盖一个已经存在的相同键'synonym'的条目,而不是保留这个已有的条目,你可以用__setitem__
来代替setdefault
,例如——很难猜测在这种特殊情况下你希望发生什么,因为你最初的要求非常模糊,而且没有提供“真实使用场景”的上下文来帮助澄清)。
编辑:在评论中澄清了使用场景(不改变原始数据结构,确实需要一个表达式,但可以使用辅助函数),我建议如下:
def addSubEntry(mainDict, outerKey, innerKey, innerValue):
# copy inner and outer dicts to avoid altering initial data
result = dict(mainDict)
inner = dict(result.get(outerKey, {}))
inner[innerKey] = innerValue
result[outerKey] = inner
return result
作为所需的表达式,使用:
addSubEntry(SOsurvivalConditions, 'firstCondition', 'synonym', 'A modern form of RTM is: Google It.')
根据在特殊情况下所需的确切行为,可能有几种变体。这个版本会在之前没有给定外键的条目时添加一个新的字典(只包含给定的内键值对);如果之前有这样的条目,它会尝试将其转换为字典(即使它原本是一个键值元组的列表),如果这样做不可行,就会抛出异常。一个更严格的版本(要求内条目已经存在并且是字典或类似字典的对象,如果不符合则抛出异常)可能会使用
inner = result[outerKey].copy()
作为主体中的第二个语句。
在编程中,有时候我们会遇到一些问题,像是代码运行不正常或者出现错误。这些问题可能是因为我们在写代码的时候,某些地方没有注意到,或者是对某些概念理解得不够清楚。
比如说,有些人可能在使用某个函数的时候,不太明白这个函数的具体作用,或者它需要什么样的输入。这就像是你在做菜时,可能会不清楚某种调料的用法,结果做出来的菜味道就不对了。
所以,遇到问题时,首先要仔细检查自己的代码,看看有没有拼写错误,或者是逻辑上有没有不合理的地方。然后,可以查阅一些资料,了解相关的知识,或者向其他人请教,获取更多的帮助。
总之,编程就像是解谜,需要耐心和细心,慢慢来,总能找到解决办法。
SOsurvivalConditions['firstCondition']['synonym'] = 'A modern form of RTM is: Google It.'