在Python中存储字典路径

时间:2012-04-29 11:26:48

标签: python dictionary

全新的python,让我说我有一个词典:

kidshair = {'allkids':{'child1':{'hair':'blonde'},
                      'child2':{'hair':'black'},
                      'child3':{'hair':'red'},
                      'child4':{'hair':'brown'}}}

如果child3定期更改头发颜色,我可能想编写一个应用程序来加速数据维护。在这个例子中,我使用:

kidshair['allkids']['child3']['hair'] = ...

有没有办法将此路径存储为变量,以便我可以访问它?显然

mypath = kidshair['allkids']['child3']['hair']

导致mypath ='red'。是否有任何可能的方法来硬编码路径本身,所以我可以使用:

mypath = 'blue' 

重复发表

kidshair['allkids']['child3']['hair'] = 'blue'

非常感谢,ATfPT

5 个答案:

答案 0 :(得分:8)

根据您的需要,最简单的选项可能是使用元组作为字典键而不是嵌套字典:

kidshair['allkids', 'child3', 'hair']
mypath = ('allkids', 'child3', 'hair')
kidshair[mypath]

唯一的问题是你无法获得字典的一部分,因此,例如,你不能(轻松/有效地)访问与'child3'有关的所有内容。根据您的使用情况,这可能是也可能不适合您。

使用当前结构的替代方法是执行以下操作:

>>> from functools import partial
>>> test = {"a": {"b": {"c": 1}}}
>>> def itemsetter(item):
...     def f(name, value):
...         item[name] = value
...     return f
...
>>> mypath = partial(itemsetter(test["a"]["b"]), "c")
>>> mypath(2)
>>> test
{'a': {'b': {'c': 2}}}

这里我们创建一个函数itemsetter(),它(在operator.itemgetter()的静脉中)为我们提供了一个函数,用于设置给定字典中的相关键。然后我们使用functools.partial生成此函数的一个版本,其中包含我们想要预先填充的键。它也不是mypath = blue,但也不错。

如果您不想为operator模块制作一致的内容,您可以这样做:

def dictsetter(item, name):
     def f(value):
         item[name] = value
     return f

mypath = dictsetter(test["a"]["b"], "c")

mypath(2)

答案 1 :(得分:6)

您可以创建一组访问“路径”的功能。对于给定的字典:

def pathGet(dictionary, path):
    for item in path.split("/"):
        dictionary = dictionary[item]
    return dictionary

def pathSet(dictionary, path, setItem):
    path = path.split("/")
    key = path[-1]
    dictionary = pathGet(dictionary, "/".join(path[:-1]))
    dictionary[key] = setItem

用法:

>>> pathGet(kidshair, "allkids/child1/hair")
'blonde'
>>> pathSet(kidshair, "allkids/child1/hair", "blue")
>>> kidshair['allkids']['child1']
{'hair': 'blue'}

答案 2 :(得分:1)

您可以轻松保存对kidshair['allkids']['child3']的引用:

thiskid = kidshair['allkids']['child3']
thiskid['hair'] = 'blue'

您无法保存整个路径,因为分配会更改hair字典中的kidshair['allkids']['child3']键。
 如果要更改字典,则必须引用它,而不是它包含的内容。

答案 3 :(得分:0)

您最接近当前数据结构的方法是获取最后一个dict并直接使用它:

child = kidshair['allkids']['child3']

child['hair'] = 'blue'

这是因为在Python中,分配了样式

name = value

只需将新对象绑定到“变量”name即可。没有办法重载这个,绑定不会影响任何其他对象(除了释放绑定到此名称的对象,直到现在。)

另一方面,这个:

name[key] = value

完全不同,因为它对当前位于name的对象执行操作(设置项目)(在您的情况下为dict)。

答案 4 :(得分:0)

尝试使用dpath lib https://pypi.org/project/dpath/

>>> help(dpath.util.new)
Help on function new in module dpath.util:

new(obj, path, value)
Set the element at the terminus of path to value, and create
it if it does not exist (as opposed to 'set' that can only
change existing keys).

path will NOT be treated like a glob. If it has globbing
characters in it, they will become part of the resulting
keys

>>> dpath.util.new(x, 'a/b/e/f/g', "Roffle")
>>> print json.dumps(x, indent=4, sort_keys=True)
{
    "a": {
        "b": {
            "3": 2,
            "43": 30,
            "c": "Waffles",
            "d": "Waffles",
            "e": {
                "f": {
                    "g": "Roffle"
                }
            }
        }
    }
}