2009-06-12 9 views
7

Pickle은 항상 특정 입력 값에 대해 동일한 출력을 생성합니까? 나는 동일한 내용을 가지고 있지만 삽입/삭제 기록이 다른 사전을 픽업 할 때 잡아 당김이있을 수 있다고 생각합니다. 필자의 목표는 Memoize 구현을 위해 Pickle과 SHA1을 사용하여 함수 인수의 "서명"을 만드는 것입니다.산세 공정이 결정적입니까?

답변

7

내용이 같지만 삽입/삭제 기록이 다른 사전을 픽업 할 때 문제가 있다고 생각합니다. 오른쪽

:

>>> pickle.dumps({1: 0, 9: 0}) == pickle.dumps({9: 0, 1: 0}) 
False 

은 참조 : pickle.dumps not suitable for hashing

내 목표는 memoize 구현에 피클과 SHA1을 사용하여, 함수 인수의 "서명"을 만드는 것입니다.

여기에는 여러 가지 근본적인 문제가 있습니다. 그것은 평등 객체 정체성의 문제를 제대로-생각 매핑하는 객체를 문자열로 변환을 마련하는 것은 불가능하다 : 당신이 그들에 객체 계층 구조를 변환 할 수 있습니다

>>> a = object() 
>>> b = object() 
>>> a == b 
False 
>>> pickle.dumps(b) == pickle.dumps(a) 
True 

당신의 정확한 요구 사항에 따라 그 그런 다음 해시 수 있습니다 :

def hashablize(obj): 
    """Convert a container hierarchy into one that can be hashed. 

    Don't use this with recursive structures! 
    Also, this won't be useful if you pass dictionaries with 
    keys that don't have a total order. 
    Actually, maybe you're best off not using this function at all.""" 
    try: 
     hash(obj) 
    except TypeError: 
     if isinstance(obj, dict): 
      return tuple((k, hashablize(v)) for (k, v) in sorted(obj.iteritems())) 
     elif hasattr(obj, '__iter__'): 
      return tuple(hashablize(o) for o in obj) 
     else: 
      raise TypeError("Can't hashablize object of type %r" % type(obj)) 
    else: 
     return obj 
0

동일한 출력으로 무엇을 의미합니까? 일반적으로 왕복 (pickling -> unpickling)에 대해 항상 동일한 출력을 얻어야하지만 직렬화 된 형식 자체는 모든 조건에서 동일하게 보장되지 않는다고 생각합니다. 물론, 그것은 플랫폼과 모든 것 사이에서 바뀔 수 있습니다.

메모 링을 위해 산 울기를 사용하는 것이 좋을 것입니다. 문제없이이 구성표를 여러 번 사용했지만 아주 간단한 문제였습니다. 한 가지 문제는 모든 유용한 사례를 다루지는 않는다는 것입니다 (함수가 마음에 들었습니다 : 피클 할 수 없으므로 함수가 호출 가능한 인수를 사용하면 작동하지 않습니다).

관련 문제