Python dill 在 defaultdict 中一次性使用默认参数
Python's dill one-time use of default argument in a defaultdict
我正在努力解决我面临的这个奇怪问题。假设我们有 defaultdict
对象的以下实例:
import dill
from collections import defaultdict
a = 1
b = 2
default_value = a/b
dict_with_default = defaultdict(lambda: default_value)
dict_with_default['a'] = 1.2
dict_with_default['b'] = 3.5
dict_with_default['c'] = 0.25
让我们看看字典的样子:
defaultdict(<function <lambda> at 0x7f860c97be18>, {'a': 1.2, 'b': 3.5, 'c': 0.25})
在保存到 dill
对象之前,我想检查字典是否正常工作 - 正常并且添加了 'd'
:
print("d: ", dict_with_default['d'])
字典现在看起来像这样:
defaultdict(<function <lambda> at 0x7f860c97be18>, {'a': 1.2, 'b': 3.5, 'c': 0.25, 'd': 0.5})
由于我必须将字典保存到文件中(以便将其传输到不同的脚本)我将其保存到dill
对象中:
with open('./pickles/simple_dict_dill.p', 'wb') as file:
dill.dump(dict_with_default, file, protocol=dill.HIGHEST_PROTOCOL)
现在让我们将注意力转向我提到的不同脚本:
import dill
with open('./pickles/simple_dict_dill.p', 'rb') as file:
simple_dict_dill = dill.load(file)
print("a:", simple_dict_dill['a'])
print("d:", simple_dict_dill['d'])
print("e:", simple_dict_dill['e']) # gives error
行 print("e:", simple_dict_dill['e'])
给出了以下错误,即使缺少密钥访问由 lambda: default_value
处理:
NameError: name 'default_value' is not defined
我以为 dill
可以序列化 lambda 函数,但事实证明它有问题。
我是 dill
的作者。这是由于 lambda
在全局字典外定义时如何序列化。您可以通过两种方式避免此错误:(1) 使用 recurse
设置,或 (2) 在全局字典中定义没有悬垂指针的 lambda。
例如:
>>> import dill
>>> dill.settings['recurse'] = True
>>> from collections import defaultdict
>>> a = 1
>>> b = 2
>>> f = lambda: a/b
>>> d = defaultdict(f)
>>> d['a'] = 3
>>> d['b'] = 4
>>> dill.dumps(d)
b'\x80\x03ccollections\ndefaultdict\nq\x00cdill._dill\n_create_function\nq\x01(cdill._dill\n_load_type\nq\x02X\x08\x00\x00\x00CodeTypeq\x03\x85q\x04Rq\x05(K\x00K\x00K\x00K\x02KCC\x08t\x00t\x01\x1b\x00S\x00q\x06N\x85q\x07X\x01\x00\x00\x00aq\x08X\x01\x00\x00\x00bq\t\x86q\n)X\x07\x00\x00\x00<stdin>q\x0bX\x08\x00\x00\x00<lambda>q\x0cK\x01C\x00q\r))tq\x0eRq\x0f}q\x10(h\x08K\x01h\tK\x02uh\x0cNN}q\x11tq\x12Rq\x13\x85q\x14Rq\x15(h\x08K\x03h\tK\x04u.'
然后我将生成的字符串剪切-N-粘贴(而不是写入文件......这是一回事)到新的 python 会话中。
$ python
Python 3.6.9 (default, Jul 6 2019, 02:58:03)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> d = dill.loads(b'\x80\x03ccollections\ndefaultdict\nq\x00cdill._dill\n_create_function\nq\x01(cdill._dill\n_load_type\nq\x02X\x08\x00\x00\x00CodeTypeq\x03\x85q\x04Rq\x05(K\x00K\x00K\x00K\x02KCC\x08t\x00t\x01\x1b\x00S\x00q\x06N\x85q\x07X\x01\x00\x00\x00aq\x08X\x01\x00\x00\x00bq\t\x86q\n)X\x07\x00\x00\x00<stdin>q\x0bX\x08\x00\x00\x00<lambda>q\x0cK\x01C\x00q\r))tq\x0eRq\x0f}q\x10(h\x08K\x01h\tK\x02uh\x0cNN}q\x11tq\x12Rq\x13\x85q\x14Rq\x15(h\x08K\x03h\tK\x04u.')
>>> d
defaultdict(<function <lambda> at 0x101d8d048>, {'a': 3, 'b': 4})
>>> d['a']
3
>>> d['c']
0.5
>>>
如果您不使用 recurse
设置,则必须使用:
>>> f = lambda: 1/2
>>> d = defaultdict(f)
当您创建 defaultdict 时。
当然,dill
应该能够更好地处理来自 lambda 的指针引用,但在某些情况下还不能。
我正在努力解决我面临的这个奇怪问题。假设我们有 defaultdict
对象的以下实例:
import dill
from collections import defaultdict
a = 1
b = 2
default_value = a/b
dict_with_default = defaultdict(lambda: default_value)
dict_with_default['a'] = 1.2
dict_with_default['b'] = 3.5
dict_with_default['c'] = 0.25
让我们看看字典的样子:
defaultdict(<function <lambda> at 0x7f860c97be18>, {'a': 1.2, 'b': 3.5, 'c': 0.25})
在保存到 dill
对象之前,我想检查字典是否正常工作 - 正常并且添加了 'd'
:
print("d: ", dict_with_default['d'])
字典现在看起来像这样:
defaultdict(<function <lambda> at 0x7f860c97be18>, {'a': 1.2, 'b': 3.5, 'c': 0.25, 'd': 0.5})
由于我必须将字典保存到文件中(以便将其传输到不同的脚本)我将其保存到dill
对象中:
with open('./pickles/simple_dict_dill.p', 'wb') as file:
dill.dump(dict_with_default, file, protocol=dill.HIGHEST_PROTOCOL)
现在让我们将注意力转向我提到的不同脚本:
import dill
with open('./pickles/simple_dict_dill.p', 'rb') as file:
simple_dict_dill = dill.load(file)
print("a:", simple_dict_dill['a'])
print("d:", simple_dict_dill['d'])
print("e:", simple_dict_dill['e']) # gives error
行 print("e:", simple_dict_dill['e'])
给出了以下错误,即使缺少密钥访问由 lambda: default_value
处理:
NameError: name 'default_value' is not defined
我以为 dill
可以序列化 lambda 函数,但事实证明它有问题。
我是 dill
的作者。这是由于 lambda
在全局字典外定义时如何序列化。您可以通过两种方式避免此错误:(1) 使用 recurse
设置,或 (2) 在全局字典中定义没有悬垂指针的 lambda。
例如:
>>> import dill
>>> dill.settings['recurse'] = True
>>> from collections import defaultdict
>>> a = 1
>>> b = 2
>>> f = lambda: a/b
>>> d = defaultdict(f)
>>> d['a'] = 3
>>> d['b'] = 4
>>> dill.dumps(d)
b'\x80\x03ccollections\ndefaultdict\nq\x00cdill._dill\n_create_function\nq\x01(cdill._dill\n_load_type\nq\x02X\x08\x00\x00\x00CodeTypeq\x03\x85q\x04Rq\x05(K\x00K\x00K\x00K\x02KCC\x08t\x00t\x01\x1b\x00S\x00q\x06N\x85q\x07X\x01\x00\x00\x00aq\x08X\x01\x00\x00\x00bq\t\x86q\n)X\x07\x00\x00\x00<stdin>q\x0bX\x08\x00\x00\x00<lambda>q\x0cK\x01C\x00q\r))tq\x0eRq\x0f}q\x10(h\x08K\x01h\tK\x02uh\x0cNN}q\x11tq\x12Rq\x13\x85q\x14Rq\x15(h\x08K\x03h\tK\x04u.'
然后我将生成的字符串剪切-N-粘贴(而不是写入文件......这是一回事)到新的 python 会话中。
$ python
Python 3.6.9 (default, Jul 6 2019, 02:58:03)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> d = dill.loads(b'\x80\x03ccollections\ndefaultdict\nq\x00cdill._dill\n_create_function\nq\x01(cdill._dill\n_load_type\nq\x02X\x08\x00\x00\x00CodeTypeq\x03\x85q\x04Rq\x05(K\x00K\x00K\x00K\x02KCC\x08t\x00t\x01\x1b\x00S\x00q\x06N\x85q\x07X\x01\x00\x00\x00aq\x08X\x01\x00\x00\x00bq\t\x86q\n)X\x07\x00\x00\x00<stdin>q\x0bX\x08\x00\x00\x00<lambda>q\x0cK\x01C\x00q\r))tq\x0eRq\x0f}q\x10(h\x08K\x01h\tK\x02uh\x0cNN}q\x11tq\x12Rq\x13\x85q\x14Rq\x15(h\x08K\x03h\tK\x04u.')
>>> d
defaultdict(<function <lambda> at 0x101d8d048>, {'a': 3, 'b': 4})
>>> d['a']
3
>>> d['c']
0.5
>>>
如果您不使用 recurse
设置,则必须使用:
>>> f = lambda: 1/2
>>> d = defaultdict(f)
当您创建 defaultdict 时。
当然,dill
应该能够更好地处理来自 lambda 的指针引用,但在某些情况下还不能。