具有相同键的(嵌套)字典的 Pythonic 替代方案?

12 投票
3 回答
8465 浏览
提问于 2025-04-30 18:13

我发现自己总是避免使用字典,因为很多时候,几乎一半的代码都是重复的。我通常是在嵌套字典中这样做,所有的子字典都包含相同的键,但值却不同。

我手动创建一个大的父字典,每个键下面都有一个嵌套字典,用于外部模块。这些嵌套字典都用相同的键来定义配置参数。这样做虽然很明确,也能正常工作,但每次手动创建嵌套字典时重新输入或复制粘贴这些键,感觉有点傻。我并不太担心内存或性能的优化,只是在想,是否有更符合Python风格的方法来做这件事。

举个简单的例子,常见的模式是:

people_dict = {
    "Charles Lindberg": {"address": "123 St.", 
                         "famous": True}, 
    "Me": {"address": "456 St.",
           "famous": False}
    }

>>>people_dict["Charles Lindberg"]["address"]
"123 St."

虽然字典让代码很明确,但定义嵌套字典时重复的键会让人觉得很麻烦,也容易出错。在这个例子中,嵌套字典的一半都是重复的代码,所有嵌套字典都有相同的部分。我试过用元组来消除重复的键,但发现这样会导致代码不稳定——位置的任何变化(而不是字典的键)都会出错。这也让代码变得不明确,难以理解。

people_dict = {
        "Charles Lindberg": ("123 St.", True), 
        "Me": ("456 St.", False),
        }    

>>>people_dict["Charles Lindberg"][0]
"123 St."

所以,我写了一个类来封装相同的信息:这样成功减少了重复的代码……

class Person(object):
    def __init__(self, address, famous=False):
        self.address = address
        self.famous = famous

people_dict = [
    "Charles Lindberg": Person("123 St.", famous=False), 
    "Me": Person("456 St."), 
    ]

>>>people_dict["Charles Lindberg"].address
"123 St." 

不过,创建一个类似乎有点过于复杂……标准数据类型又显得太简单了……

我想在Python中应该有更好的方法来做到这一点,而不需要自己写类?

在创建具有相同键的嵌套字典时,避免重复代码的最佳方法是什么?

暂无标签

3 个回答

1

首先,你可以点击上面的链接了解更多关于命名元组(namedtuple)的信息:https://docs.python.org/2/library/collections.html#collections.namedtuple

命名元组可以帮助你避免“重复代码”。你可以为地址创建一个命名元组,然后用它来定义地址。
我个人更喜欢面向对象(Object)的方法。面向对象对这个问题有更好的解决方案。你可以创建一个方法,把对象导出为字典(dict)。

如果你更倾向于函数式编程,使用列表、数组和字典会更好,因为有很多方法和函数可以帮助处理这些结构(比如map、reduce等)。如果你不打算在你的应用中使用函数式编程,那就选择面向对象的解决方案吧。

祝好,
安德烈

2

如果你想要一个字典,其中所有的值都是有相同或相似键的字典,你可以定义一个函数,这个函数接收这些值并返回其中一个内部的字典。

def hash(address, famous): return {"address": address, "famous": famous}

people_dict = {
    "Charles Lindberg": hash("123 St.", true),
    "Me": hash("456 St.", false)
}
6

听起来你有一组数据,就像一个矩阵,因为每一“行”都有相同的键(列)。所以我建议你使用NumPy数组:

import numpy as np

dtype = [('name', object), ('address', object), ('famous', bool)]
people = np.array([
        ("Charles Lindberg", "123 St.", True),
        ("Me", "456 St.", False),
        ], dtype)

charlie = people[people['name'] == 'Charles Lindberg'][0]
print charlie['address']

或者你也可以用Pandas,这个工具更高级一些:

import pandas as pd
people = pd.DataFrame(people_dict)
print people['Charles Lindberg']['address']

这样可以很轻松地把你原来的字典(people_dict)直接加载到矩阵中,并且提供类似的查找功能。

撰写回答