Python 作为变量的嵌套dict键

Python 作为变量的嵌套dict键,python,Python,必须有一种更优雅的方法来实现这一点,但我不知道如何创建一个函数来读取/写入dict的不同级别的值,这是我能想到的“最佳”方法: table = { 'A': { 'B': '2', 'C': { 'D':'3' } } } first = 'A' second1 = 'B' second2 = 'C' third = 'D' def oneLevelDict(first): x = table[fi

必须有一种更优雅的方法来实现这一点,但我不知道如何创建一个函数来读取/写入dict的不同级别的值,这是我能想到的“最佳”方法:

table = {
    'A': {
        'B': '2',
        'C': {
            'D':'3'
        }
    }
}
first = 'A'
second1 = 'B'
second2 = 'C'
third = 'D'

def oneLevelDict(first):
    x = table[first]
    print(x)

def twoLevelDict(first, second):
    x = table[first][second]
    print(x)

def threeLevelDict(first, second, third):
    x = table[first][second][third]
    print(x)

oneLevelDict(first)
twoLevelDict(first, second1)
threeLevelDict(first, second2, third)

可以使用*args向函数传递任意数量的参数。然后可以使用循环遍历标高

get_any_level(*keys):
    d = table
    for key in keys:
        d = d[key]
    return d
现在,您有一个功能可以取代以前的三个功能:

print(get_any_level(first))
print(get_any_level(first, second1))
print(get_any_level(first, second2, third))
您也可以使用此函数写入任意级别:

get_any_level(first)[second1] = 17
更好的方法可能是使用单独的函数来编写:

def put_any_level(value, *keys):
    get_any_level(*keys[:-1])[keys[-1]] = value

put_any_level(17, first, second1)
value
必须位于参数列表的第一位,除非您希望它仅为关键字,因为
*键将使用所有位置参数。这不一定是一个坏的选择:

def put_any_level(*keys, value):
    get_any_level(*keys[:-1])[keys[-1]] = value
关键字参数增加了清晰度:

put_any_level(first, second1, value=17)
但是,如果试图将其作为位置参数传递,也会导致错误,例如,
将其置于任何级别(第一、第二、17)

几个小问题:

  • 通常只对类名使用CamelCase。变量和函数通常用小写字母_加下划线表示
  • 函数通常应该做一件事,并且做得很好。在本例中,我通过给函数一个返回值,将查找嵌套值的任务与显示嵌套值的任务分开

  • 这可以使用*args实现。阅读更多关于它的信息

    这就是如何做到这一点:

    def allLevelDict(*argv):
      if len(argv) == 1:
        x  = table[argv[0]]
        print (x)
      elif len(argv) == 2:
        x  = table[argv[0]][argv[1]]
        print (x)
      elif len(argv) == 3:
        x  = table[argv[0]][argv[1]][argv[2]]
        print (x)
    allLevelDict(first)
    allLevelDict(first, second1)
    allLevelDict(first, second2, third)
    

    与其他建议类似,但如果您喜欢递归,可能会更优雅:

    table = {'A':{'B':'2','C':{'D':'3'}}}
    first = 'A'
    second1 = 'B'
    second2 = 'C'
    third = 'D'
    
    
    def get_from(x, *keys):
        return get_from(x[keys[0]], *keys[1:]) if len(keys) > 0 else x
    
    
    print(get_from(table, first))
    print(get_from(table, first, second1))
    print(get_from(table, first, second2, third))
    
    注意:我也在传递表格,因为我想你也希望能在其他字典上使用它

    或者,如果你认为越短越好:

    def get_from(x, *keys):
        if len(keys) > 0 
            return get_from(x[keys[0]], *keys[1:])
        else:
            return x
    

    通常情况下,递归可能是危险的,因为它很昂贵——但因为你不太可能有非常深刻的字典,我觉得这是正确的解决方案。

    不是一个完全的骗局,但在某种程度上是相关的:@TrebuchetMS,这两个问题都是关于字典的,但这个问题是关于如何在字典的任意级别访问值的。这是一个比我的更好的答案。@Aditya。我很感激你这么说。@MadPhysicator-谢谢你解释这一点*阿格斯是关键!也要欣赏会议技巧-新语言-新会议。@MattYYC很高兴你喜欢它。您可以通过单击旁边的复选标记来选择答案。通过
    x=table[first]
    您的意思是
    x=table[argv[0]]
    ?@madpysicator现在更改了它。谢谢。谢谢@AdityaK!也是对*argsThanks@Grismar的一个很好的解释-非常简洁。[1:]是否等效于popitems()?不确定这是什么意思。
    [1:://code>表示“序列中的所有元素,从索引1处的元素开始”。因此,对于
    x=[1,2,3,4]
    x[1:]
    将是
    [2,3,4]
    -在这里阅读更多关于这一点的内容,称为“切片”,它不等同于
    popitem()
    ,不仅因为它返回序列的更大部分,更重要的是因为它不修改原始内容,而是返回其内容的副本。