11

全新的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

4

5 回答 5

11

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

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)
于 2012-04-29T11:29:49.723 回答
9

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

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'}
于 2012-04-29T11:55:37.337 回答
2

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

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

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

于 2012-04-29T11:34:02.490 回答
1

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

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

child['hair'] = 'blue'

这是因为在 Python 中,样式的赋值

name = value

只需将新对象绑定到“变量” name。无法重载 this 并且绑定不会影响任何其他对象(除了释放之前绑定到此名称的对象)。

另一方面是:

name[key] = value

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

于 2012-04-29T11:33:47.133 回答
1

尝试使用 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"
                }
            }
        }
    }
}
于 2019-10-31T08:36:44.213 回答