TL;博士;跳转到此答案的底部查看工作代码
我肯定有些人讨厌
pickle
在重构代码时(当pickle对象的类移动到不同的文件时),它肯定会带来一些麻烦。但更大的问题是泡菜是不安全的,只是YAML妨碍了你使用它。
有趣的是,您不能将pickle设置为更可读的
protocol level 0
泡菜。转储(rngdct,f,协议=0)
将抛出:
插槽
不能腌制
这是因为
RangeDict
模块/类有点简约,这也表明(或者更确切地说不是)如果你试图做:
print(rngdict)
只需打印
{}
dump()
load()
). 尽管这可能会转储通用Python类,但您必须意识到这是在Python 3.0之前实现的,或者与Python 3.0大致同时实现的。(稍后实现了对Python 3的支持)。尽管YAML解析器没有理由转储和加载
是的,它不会与
泡菜
无论如何,没有特定的重新输入(和构造函数)
RangeDict公司
对象,使用YAML真的没有任何意义:它使得加载可能不安全,并且您的YAML包括
这使得该对象高效。如果你这样做了
yaml.dump()
!!python/object:rangedict.RangeDict
_root: &id001 !!python/object/new:rangedict.Node
state: !!python/tuple
- null
- color: 0
left: null
parent: null
r: !!python/tuple [1, 9]
right: !!python/object/new:rangedict.Node
state: !!python/tuple
- null
- color: 1
left: null
parent: *id001
r: !!python/tuple [10, 19]
right: null
value: {Series: '1', Type: B}
value: {Series: '1', Type: A}
可读
在YAML中的代表将是:
!rangedict
[1, 9]:
Type: A
Series: '1'
[10, 19]:
Type: B
Series: '1'
ruamel.yaml
RangeDict公司
要提供合适的重新输入和构造函数(类)方法:
import io
import ruamel.yaml
from rangedict import RangeDict
class MyRangeDict(RangeDict):
yaml_tag = u'!rangedict'
def _walk(self, cur):
# walk tree left -> parent -> right
if cur.left:
for x in self._walk(cur.left):
yield x
yield cur.r
if cur.right:
for x in self._walk(cur.right):
yield x
@classmethod
def to_yaml(cls, representer, node):
d = ruamel.yaml.comments.CommentedMap()
for x in node._walk(node._root):
d[ruamel.yaml.comments.CommentedKeySeq(x)] = node[x[0]]
return representer.represent_mapping(cls.yaml_tag, d)
@classmethod
def from_yaml(cls, constructor, node):
d = cls()
for x, y in node.value:
x = constructor.construct_object(x, deep=True)
y = constructor.construct_object(y, deep=True)
d[x] = y
return d
rngdct = MyRangeDict()
rngdct[(1, 9)] = \
{"Type": "A", "Series": "1"}
rngdct[(10, 19)] = \
{"Type": "B", "Series": "1"}
yaml = ruamel.yaml.YAML()
yaml.register_class(MyRangeDict) # tell the yaml instance about this class
buf = io.StringIO()
yaml.dump(rngdct, buf)
data = yaml.load(buf.getvalue())
# test for round-trip equivalence:
for x in data._walk(data._root):
for y in range(x[0], x[1]+1):
assert data[y]['Type'] == rngdct[y]['Type']
assert data[y]['Series'] == rngdct[y]['Series']
buf.getvalue()
正是前面显示的可读表示。
如果你不得不面对倾销
本身(即,由于您使用的某些库具有
硬编码),然后可以添加
MyRangeDict
RangeDict公司
通过嫁接/修补。