【问题标题】:How to retain the type of list elements after stored in a dictionary?存储在字典中后如何保留列表元素的类型?
【发布时间】:2020-02-20 06:21:26
【问题描述】:

我有一个嵌套字典,格式如下。

import pickle

db = {'obj 1':
        {
        'a' : 1, 'b' : 2, 'c' : 3,
        'foo': [0, a, a+b, 2*a, 2*(b+c)],
        'bar': [c, c+a, c-b, 2*c, 2*a]
        },
    'obj 2':
        {
        'a' : 4, 'b' : 5, 'c' : 6,
        'foo': [0, a, a+b, 2*a, 2*(b+c), 0, 0],
        'bar': [c, c+a, c-b, 2*c, 2*a, 0, 0]
        },
}

with open("db.pkl", "wb") as pkl:
    pickle.dump(db, pkl)

print(db)

它抛出了这个错误:

Traceback (most recent call last):
  File "dmy.py", line 8, in <module>
    'foo': [0, a, a+b, 2*a, 2*(b+c)],
NameError: name 'a' is not defined

我有什么办法可以让dmy = db['obj 1']['foo'] 的输出成为[0, a, a+b, 2*a, 2*(b+c)],这是一个列表。 我知道我所做的可能不是正确的方法,但我需要像这样将内容放在一起。

注意:我已经尝试将列表元素单独转换为字符串,但是在解析时,我无法获取这种指定形式的内容,即[0, a, a+b, 2*a, 2*(b+c)]

我能找到的最接近的是这个链接Python - is there a way to store an operation(+ - * /) in a list or as a variable?

【问题讨论】:

  • 将列表放在引号中"[0, a, a+b, 2*a, 2*(b+c)]" 这将解决错误
  • 但是解析后如何将'foo'的值保留为列表?我试过了,它是一种字符串。无论如何,我可以将其转换回列表形式而无需进行大量字符串操作?
  • 我们可以转换为列表,但列表中的变量仍然是字符串。如果我们改变我们不能改变变量我们得到错误a is not defined
  • @RajuKomati 没错。我编辑了问题以包含更多信息。我想按原样保留列表元素。

标签: python list dictionary pickle


【解决方案1】:

问题在于abc 是您的(尚不存在的)dict 的成员。它们不是变量,所以

    {
    'a' : 1, 'b' : 2, 'c' : 3,
    'foo': [0, a, a+b, 2*a, 2*(b+c)],
    'bar': [c, c+a, c-b, 2*c, 2*a]
    },

没用。

您可以通过以下方式解决此问题:

import pickle

def build_dict(a, b, c, add=None):
    if add is None: add = []
    return {
        'a': a, 'b': b, 'c' : c,
        'foo': [0, a, a+b, 2*a, 2*(b+c)] + add,
        'bar': [c, c+a, c-b, 2*c, 2*a] + add
    }

db = {'obj 1': build_dict(1, 2, 3),
      'obj 2': build_dict(4, 5, 6, [0, 0])}

with open("db.pkl", "wb") as pkl:
    pickle.dump(db, pkl)

print(db)

这使得变量abc 存在并且可用。

另一种方法是

    transform({'a' : 1, 'b' : 2, 'c' : 3, lambda a, b, c: {'foo': [0, a, a+b, 2*a, 2*(b+c)], 'bar': [c, c+a, c-b, 2*c, 2*a]})
    transform({'a' : 4, 'b' : 5, 'c' : 6, lambda a, b, c: {'foo': [0, a, a+b, 2*a, 2*(b+c), 0, 0], 'bar': [c, c+a, c-b, 2*c, 2*a, 0, 0]})

def transform(base, transform):
    base.update(transform(**base))
    return base

    transform({'a' : 1, 'b' : 2, 'c' : 3, lambda base: {'foo': [0, base['a'], base['a']+base['b'], 2*base['a'], 2*(base['b']+base['c'])], 'bar': [base['c'], base['c']+base['a'], base['c']-base['b']b, 2*base['c'], 2*base['a']]})
    transform({'a' : 4, 'b' : 5, 'c' : 6, lambda base: {'foo': 0, base['a'], base['a']+base['b'], 2*base['a'], 2*(base['b']+base['c']), 0, 0], 'bar': [base['c'], base['c']+base['a'], base['c']-base['b']b, 2*base['c'], 2*base['a'], 0, 0]})

def transform(base, transform):
    base.update(transform(**base))
    return base

【讨论】:

  • 感谢您的回答。我理解你的意思,但信息需要以这种形式存储并检索,因为它们都是数据库中同一元素的一部分。因此,我很难在获得所需的值之前传递它们。我想知道在 Python 中是否有任何方法可以做到这一点。
  • @snair.stack 不,没有,至少不是直接的。有可能创建一个“基本字典”,然后通过使用它的值来修改它。
【解决方案2】:

你可以用 lambda 函数替换你的列表推导,然后用 dill (https://pypi.org/project/dill/) 代替 pickle:

import dill

db = {'obj 1':
        {
        'a' : 1, 'b' : 2, 'c' : 3,
        'foo': lambda a, b, c : [0, a, a+b, 2*a, 2*(b+c)],
        'bar': lambda a, b, c : [c, c+a, c-b, 2*c, 2*a]
        },
    'obj 2':
        {
        'a' : 4, 'b' : 5, 'c' : 6,
        'foo': lambda a, b, c : [0, a, a+b, 2*a, 2*(b+c), 0, 0],
        'bar': lambda a, b, c : [c, c+a, c-b, 2*c, 2*a, 0, 0]
        },
}

print(db)

pickled_db = dill.dumps(db)
unpickled_db = dill.loads(pickled_db)

print(unpickled_db)

【讨论】:

    【解决方案3】:

    现在我设法使用eval 解决了这个问题。我使用的代码如下。

    import pickle
    
    db = {'obj 1':
            {
            'a' : 1,
            'b' : 2,
            'c' : 3,
            'foo': ['0', 'a', 'a+b', '2*a', '2*(b+c)'],
            'bar': ['c', 'c+a', 'c-b', '2*c', '2*a']
            },
        'obj 2':
            {
            'a' : 4,
            'b' : 5,
            'c' : 6,
            'foo': ['0', 'a', 'a+b', '2*a', '2*(b+c)', '0', '0'],
            'bar': ['c', 'c+a', 'c-b', '2*c', '2*a', '0', '0']
            },
    }
    
    with open("db.pkl", "wb") as pkl:
        pickle.dump(db, pkl)
    print(db)
    with open("db.pkl", "rb") as pkl:
        db_pkl = pickle.loads(pkl.read())
    
    a = db_pkl['obj 1']['a']
    b = db_pkl['obj 1']['b']
    c = db_pkl['obj 1']['c']
    arr = db_pkl['obj 1']['foo']
    
    arr_foo = []
    for i in range(0, len(arr)):
        foo = eval(arr[i])
        arr_foo.append(foo)
    print("\n", arr_foo)
    

    输出:

    {'obj 1': {'a': 1, 'b': 2, 'c': 3, 'foo': ['0', 'a', 'a+b', '2*a', '2*(b+c)'], 'bar': ['c', 'c+a', 'c-b', '2*c', '2*a']}, 'obj 2': {'a': 4, 'b': 5, 'c': 6, 'foo': ['0', 'a', 'a+b', '2*a', '2*(b+c)', '0', '0'], 'bar': ['c', 'c+a', 'c-b', '2*c', '2*a', '0', '0']}}
    
     [0, 1, 3, 2, 10]
    

    它不保留变量名,而是计算它。 如果有人有更清洁、更好或替代的方法来做到这一点,请随时编辑或发布答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-11
      • 1970-01-01
      • 2015-01-20
      • 1970-01-01
      • 1970-01-01
      • 2014-10-10
      • 1970-01-01
      相关资源
      最近更新 更多