具有相同键的(嵌套)字典的 Pythonic 替代方案?
我发现自己总是避免使用字典,因为很多时候,几乎一半的代码都是重复的。我通常是在嵌套字典中这样做,所有的子字典都包含相同的键,但值却不同。
我手动创建一个大的父字典,每个键下面都有一个嵌套字典,用于外部模块。这些嵌套字典都用相同的键来定义配置参数。这样做虽然很明确,也能正常工作,但每次手动创建嵌套字典时重新输入或复制粘贴这些键,感觉有点傻。我并不太担心内存或性能的优化,只是在想,是否有更符合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 个回答
首先,你可以点击上面的链接了解更多关于命名元组(namedtuple)的信息:https://docs.python.org/2/library/collections.html#collections.namedtuple
命名元组可以帮助你避免“重复代码”。你可以为地址创建一个命名元组,然后用它来定义地址。
我个人更喜欢面向对象(Object)的方法。面向对象对这个问题有更好的解决方案。你可以创建一个方法,把对象导出为字典(dict)。
如果你更倾向于函数式编程,使用列表、数组和字典会更好,因为有很多方法和函数可以帮助处理这些结构(比如map、reduce等)。如果你不打算在你的应用中使用函数式编程,那就选择面向对象的解决方案吧。
祝好,
安德烈
如果你想要一个字典,其中所有的值都是有相同或相似键的字典,你可以定义一个函数,这个函数接收这些值并返回其中一个内部的字典。
def hash(address, famous): return {"address": address, "famous": famous}
people_dict = {
"Charles Lindberg": hash("123 St.", true),
"Me": hash("456 St.", false)
}
听起来你有一组数据,就像一个矩阵,因为每一“行”都有相同的键(列)。所以我建议你使用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
)直接加载到矩阵中,并且提供类似的查找功能。