2014-10-25 5 views
0

shelve 모듈에 대한 래퍼 클래스를 작성 중이므로 사전과 같이 사용하려고합니다. 코드는 다음과 같습니다.Python에서 shelve 모듈과 함께 __repr__ 사용

import shelve 

class MyShelve: 

    def __init__(self, filename='myshelve.db'): 
     self.s = shelve.open(filename) 

    def __del__(self): 
     self.s.close() 

    def __repr__(self): 
     return repr(self.s) 

    def __getitem__(self, k): 
     return self.s.get(k, None) 

    def __setitem__(self, k, v): 
     self.s[k] = v 

"key in dict"표현을 사용하기 전까지는 모든 것이 잘 작동하는 것처럼 보였습니다. 다음은 세션 예입니다.

>>> d = {'1': 'One', '2': 'Two'} 
>>> d 
{'1': 'One', '2': 'Two'} 
>>> '1' in d 
True 
>>> from myshelve import MyShelve 
>>> s = MyShelve() 
>>> s['1'] = 'One' 
>>> s['2'] = 'Two' 
>>> s 
{'1': 'One', '2': 'Two'} 
>>> '1' in s.s 
True 
>>> '1' in s 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "myshelve.py", line 15, in __getitem__ 
    return self.s.get(k, None) 
    File "/usr/lib64/python2.7/shelve.py", line 113, in get 
    if key in self.dict: 
    File "/usr/lib64/python2.7/_abcoll.py", line 369, in __contains__ 
    self[key] 
    File "/usr/lib64/python2.7/bsddb/__init__.py", line 270, in __getitem__ 
    return _DeadlockWrap(lambda: self.db[key]) # self.db[key] 
    File "/usr/lib64/python2.7/bsddb/dbutils.py", line 68, in DeadlockWrap 
    return function(*_args, **_kwargs) 
    File "/usr/lib64/python2.7/bsddb/__init__.py", line 270, in <lambda> 
    return _DeadlockWrap(lambda: self.db[key]) # self.db[key] 
TypeError: Integer keys only allowed for Recno and Queue DB's 

내가 뭘 잘못하고 있니?

+1

's.keys()'를 사용해야합니다. –

+0

나는 그것을 시도하고 나에게이 오류 준 : 에 AttributeError를 파일 "", 라인 1 : '>>> s.keys()를 역 추적 (가장 최근 통화 마지막) MyShelve 인스턴스가 어떤 속성이 없습니다 'keys'' "key in dict"표현식을 좋아하고 영구적 사전에 구현하고 싶습니다. – czayas

+0

15 분 안에 답변 해 드리겠습니다. 문제는'__getitem__'과'__setitem__'을 잘못하고있는 것입니다. 문서를보십시오. –

답변

1

맨 먼저 항상 object에서 상속됩니다. 그것은 나중에 많은 문제에서 당신을 구할 것입니다. 둘째, __contains__을 사용해야합니다. 셋째, __contains__ 또는 __getitem__ 또는 임의의 dunder 메소드를 사용하는 경우 try-except 블록을 의미하는 예외를 사용해야합니다. 여기에 당신이 찾고있는 무엇의 예입니다

class MyShelve(object): 

    def __init__(self, filename='myshelve.db'): 
     self.s = shelve.open(filename) 

    def __del__(self): 
     self.s.close() 

    def __repr__(self): 
     return repr(self.s) 

    def __getitem__(self, item): 
     return self.s.get(item, False) 

    def __contains__(self, item): 
     try: 
      return item in self.s 
     except TypeError: 
      return False 

    def __setitem__(self, k, v): 
     self.s[k] = v 

데모 : 예외없이이로 평가 것이라고 표현 3 in s을 차단하는 것이

In[3]: from shelving import MyShelve 
In[4]: s = MyShelve() 
In[5]: s['1'] = 'One' 
In[6]: s['2'] = 'Two' 
In[7]: '1' in s 
Out[7]: True 

참고 :

Traceback (most recent call last): 
(...) 
TypeError: gdbm key must be string, not int 

에서 시간이 오래 걸리므로 미리 구성된 값을 가진 함수를 사용하는 것이이 경우 클래스를 사용하는 것보다 낫습니다. 왜냐하면 많은 것을 덮어 쓸 것이므로 시간을 낭비하게됩니다. 또한 파일 객체를 캡슐화하는 클래스가 아니라 파일 객체를 반환하는 함수로 컨텍스트 관리자를 사용하는 것이 더 쉽습니다. 쉘프를 열면 실제로 파일을 만들 수 있기 때문입니다.

+0

감사합니다. 나는 블록을 제외하고 시도의 중요성을 고려하지 않았다. – czayas

+0

@czayas 내 조언은 선반을 덮는 수업을 전혀 갖지 않는 것입니다. 컨텍스트 관리자 및'shelve.open()'이 제공하는 다른 것들을 얻을 수는 없습니다. 또한,이 대답이 도움이된다면 upvote를 잊지 마세요 :) –

1

__contain__ 방법을 사용하고 사례를 사용자 지정하십시오. 그것은 "in"연산자가 호출하는 것입니다.

class MyShelve: 

    def __init__(self,filename='myshelve.db'): 
     self.s = shelve.open(filename) 

    def __del__(self): 
     self.s.close() 

    def __repr__(self): 
     return repr(self.s) 

    def __getitem__(self, k): 
     return self.s.get(k, None) 

    def __setitem__(self, k, v): 
     self.s[k] = v 
    def __contains__(self, m): 
      return True if (m in self.s.values() or self.s.keys) else False 

    def close(self): 
     self.s.close() 

    def clear(self): 
     self.s.clear() 

    def items(self): 
     return self._shelve.iteritems() 

s= MyShelve() 

s['1'] = 'One' 
s['2'] = 'two' 
print '1' in s #Output: True 
+0

그는 선반이 아니라 딕터가 필요합니다. –

+0

@Games Brainiac : 예, 동일한 결과가 나타납니다. –

+0

동의하지만, dict를 캡슐화하기위한 클래스를 만들고 기본 메소드를 기본 메소드로 미러링하여 기본 메소드를 덮어 쓰는 경우 많은 작업을 수행하지 않습니다. –

관련 문제