TL; 나는 어떤 사람들은 (절인 객체의 클래스가 다른 파일을 이동할 때) 코드를 리팩토링 할 때, 그것은 확실히 약간의 두통을 줄 수 pickle
싫어 확신 코드
작업이 대답의 바닥으로 건너 뜁니다. 그러나 더 큰 문제는 장아찌가 안전하지 않다는 것입니다. 단지 YAML이 당신이 사용했던 방식입니다. 것 (= 0 rngdct, F, 프로토콜)
pickle.dump :
그것은 당신이 더 많은 읽을 수 protocol level 0에 피클 수 없음을주의하는 것이 재미뿐만 (파이썬 3에서 기본 프로토콜 버전 3)이다 던져 :
TypeError: a class that defines slots without defining getstate cannot be pickled
을 RangeDict
모듈/클래스는, 조금 최소한의 때문은 또한 어떤 쇼 (또는 오히려하지 않습니다) 당신이하려고하면 :
print(rngdict)
단지
{}
당신은 아마 PyYAML
dump()
루틴을 사용
인쇄됩니다
(그리고 그것의 대응, 안전하지 않은, load()
). 파이썬이 일반적인 파이썬 클래스를 덤프 할 수는 있지만 파이썬 3.0 이전에 또는 대략 동시에 구현되었다는 것을 알아야합니다. (그리고 Python 3 지원은 나중에 구현되었다). 그리고 YAML 파서가 pickle
이하는 정확한 정보를 덤프하고로드 할 이유는 없지만 pickle
지원 루틴에 연결할 수는 있지만 Python 3 특정 산세 프로토콜에 대한 정보에는 포함되지 않습니다. 그것은 잠재적으로 안전하지 않은로드하게하고 YAML 개체가 효율적으로 그 피투성이의 세부 사항 모두 포함 : 정말 이해가되지 않습니다 YAML을 사용
RangeDict
객체에 대한 특정 representer (그리고 생성자)없이 어떤 방법, .당신이 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에
읽을 수 표현 될 경우 IMO 다음에
때문에 키로서 사용되는 시퀀스의
!rangedict
[1, 9]:
Type: A
Series: '1'
[10, 19]:
Type: B
Series: '1'
,이 PyYAML에 의해로드 할 수없는 주요 수정 파서. 그러나 다행스럽게도, 그 수정이 ruamel.yaml
에 통합 된
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']
: "모두가"당신이해야 할 (면책 조항 나는 그 패키지의 저자), 그래서 적절한 representer와 생성자 (클래스) 방법을 제공하는 서브 클래스
RangeDict
입니다
buf.getvalue()
은 정확히 이전에 읽을 수있는 표현입니다. 당신이 (당신이 하드 코드 RangeDict
을 가지고 몇 가지 라이브러리를 사용하기 때문에 즉 서브 클래스 수 없습니다) RangeDict
자체를 덤핑 처리해야하는 경우
는, 당신은 이식/monkeypatching 기준에 대한 특성 및 MyRangeDict
직접 RangeDict
의 방법을 추가 할 수 있습니다.
나는'NSStock'가 오타라고 생각합니다. 그렇지 않다면 당신의 예제에 그 정의를 추가하십시오. – Anthon
맞아요! 죄송합니다. 변수 이름을 변경했지만 잊어 버렸습니다. 발언 해줘서 고마워! @Anthon –