在 Python 中存储字典路径


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

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

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)

您可以创建一组函数来访问给定字典的"路径":

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'}

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

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

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

尝试使用 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"
                }
            }
        }
    }
}

您可以对当前数据结构做的最接近的事情是获取最后一个字典并直接使用它:

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

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

name = value

只需将新对象绑定到"变量"name。没有办法重载它,绑定不能影响任何其他对象(除了释放到目前为止绑定到此名称的对象)。

另一方面,这个:

name[key] = value

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

最新更新