繁体   English   中英

python根据键列表获取指向嵌套字典/列表组合中项目的指针

[英]python get pointer to an item in a nested dictionary/list combination based on a list of keys

我有一个看起来像这样的数据结构:

someData = {"apple":{"taste":"not bad","colors":["red","yellow"]},
"banana":{"taste":"perfection","shape":"banana shaped"},
"some list":[6,5,3,2,4,6,7]}

以及描述此结构中某个项目的路径的键列表

someList = ["apple","colors",2]

我已经有一个函数getPath(path) (见下文),它应该返回一个指向所选对象的指针。 它适合阅读,但我在尝试写作时遇到了麻烦

print(getPath(someList))
>> yellow

getPath(someList) = "green"
>> SyntaxError: can't assign to function call

a = getPath(someList)
a = "green"
print(getPath(someList))
>> "yellow"

有没有办法使这项工作? 也许是这样的:

someFunc(someList, "green")
print(getPath(someList))
>> green

这个问题看起来像这个问题,只是我想给那个项目写点东西,而不仅仅是阅读它。
我的实际数据可以在这里看到(我使用 json.loads() 来解析数据)。 请注意,我计划向此结构添加内容。 我想要一个通用的方法来证明项目的未来。

我的代码:

def getPath(path):
    nowSelection = jsonData
    for i in path:
        nowSelection = nowSelection[i]
    return nowSelection

您从getPath()获得的结果是字典或列表中的不可变 该值甚至不知道它存储在字典或列表中,并且您无法更改它。 您必须更改字典/列表本身。

例子:

a = {'hello': [0, 1, 2], 'world': 2}
b = a['hello'][1]
b = 99             # a is completely unaffected by this

与之比较:

a = {'hello': [0, 1, 2], 'world': 2}
b = a['hello']     # b is a list, which you can change
b[1] = 99          # now a is {'hello': [0, 99, 2], 'world': 2}

在您的情况下,不是沿着路径一路找到您想要的值,而是一路走除了最后一步,然后修改您从倒数第二步获得的字典/列表:

getPath(["apple","colors",2]) = "green"  # doesn't work
getPath(["apple","colors"])[2] = "green" # should work

您可以使用自定义缓存功能缓存您的getPath ,该功能允许您手动填充保存的缓存。

from functools import wraps

def cached(func):
    func.cache = {}
    @wraps(func)
    def wrapper(*args):
        try:
            return func.cache[args]
        except KeyError:
            func.cache[args] = result = func(*args)
            return result   
    return wrapper


@cached
def getPath(l):
    ...

getPath.cache[(someList, )] = 'green'
getPath(someList)  # -> 'green'

你不能从字面上做你想做的事。 我认为你能得到的最接近的是传递新值,然后在函数中手动重新分配它:

someData = {"apple":{"taste":"not bad","colors":["red","yellow"]}, "banana":{"taste":"perfection","shape":"banana shaped"}, "some list":[6,5,3,2,4,6,7]}

def setPath(path, newElement):
    nowSelection = someData
    for i in path[:-1]:  # Remove the last element of the path
        nowSelection = nowSelection[i]

    nowSelection[path[-1]] = newElement  # Then use the last element here to do a reassignment

someList = ["apple","colors",1]

setPath(someList, "green")

print(someData) 

{'apple': {'taste': 'not bad', 'colors': ['red', 'green']}, 'banana': {'taste': 'perfection', 'shape': 'banana shaped'}, 'some list': [6, 5, 3, 2, 4, 6, 7]}

我将其重命名为setPath以更好地反映其目的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM