列表元素存入字典后如何保留类型?
How to retain the type of list elements after stored in a dictionary?
我有一个嵌套字典,其形式如下。
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)]
.
我能找到的最接近的是这个 link
问题是 a
、b
和 c
是您的(尚不存在的)字典的成员。它们不是变量,所以
{
'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)
这使得变量 a
、b
和 c
存在并可用。
另一种方法可以是
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
您可以用 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)
现在我设法使用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]
它不保留变量名,而是计算它。
如果有人有更清洁、更好或替代的方法来做到这一点,请随时编辑或 post 回答。
我有一个嵌套字典,其形式如下。
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)]
.
我能找到的最接近的是这个 link
问题是 a
、b
和 c
是您的(尚不存在的)字典的成员。它们不是变量,所以
{
'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)
这使得变量 a
、b
和 c
存在并可用。
另一种方法可以是
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
您可以用 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)
现在我设法使用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]
它不保留变量名,而是计算它。 如果有人有更清洁、更好或替代的方法来做到这一点,请随时编辑或 post 回答。