2013-08-23 6 views
0

O'Reilly의 Python Cookbook (제 2 판)에서 레시피를 구현하려고하는데, 레시피의 일부분이 제대로 작동하지 않습니다. 나는 왜 누군가가 나를 이해할 수 있기를 바랬다.파이썬 요리 책의 레시피

레시피는 "5.14 : 등급 기능으로 사전 형식 향상"입니다. 대부분의 코드가 작동하지만 키의 '순위'를 변경하려고하면 오류가 발생합니다. 저자의 의견대로 모든 의견을 남겼습니다. 도움을 얻으려는 사람은 누구나 "언더"와 "던더"에 대한 좋은 생각을 갖게됩니다. 특히 "_rating"측면, 나는 그것이 어떻게 든 오류를 일으키는 것으로 믿습니다.

ERROR :

File "rating.py", line 119, in <module> 
    r["john"]=20 
    File "rating.py", line 40, in __setitem__ 
    del self._rating[self.rating(k)] ## 
AttributeError: 'Ratings' object has no attribute 'rating' 

CODE :

class Ratings(UserDict.DictMixin, dict): 
    '''The implementation carefully mixes inheritance and delegation 
    to achieve reasonable performance while minimizing boilerplate, 
    and, of course, to ensure semantic correctness as above. All 
    mappings' methods not implemented below get inherited, mostly 
    from DictMixin, but, crucially!, __getitem__ from dict. ''' 

    def __init__(self, *args, **kwds): 
     ''' This class gets instantiated just like 'dict' ''' 
     dict.__init__(self, *args, **kwds) 
     # self._rating is the crucial auxiliary data structure: a list 
     # of all (value, key) pairs, kept in "natural"ly-sorted order 
     self._rating = [ (v, k) for k, v in dict.iteritems(self) ] 
     self._rating.sort() 

    def copy(self): 
     ''' Provide an identical but independent copy ''' 
     return Ratings(self) 

    def __setitem__(self, k, v): 
     ''' besides delegating to dict, we maintain self._rating ''' 
     if k in self: 
      del self._rating[self.rating(k)] ## 
     dict.__setitem__(self, k, v) 
     insort_left(self._rating, (v, k)) 

    def __delitem__(self, k): 
     ''' besides delegating to dict, we maintain self._rating ''' 
     del self._rating[self.rating(k)] 
     dict.__delitem__(self, k) 
     ''' delegate some methods to dict explicitly to avoid getting 
     DictMixin's slower (though correct) implementations instead ''' 
     __len__ = dict.__len__ 
     __contains__ = dict.__contains__ 
     has_key = __contains__ 
     ''' the key semantic connection between self._rating and the order 
     of self.keys() -- DictMixin gives us all other methods 'for 
     free', although we could implement them directly for slightly 
     better performance. ''' 

     def __iter__(self): 
      for v, k in self._rating: 
       yield k 
      iterkeys = __iter__ 

     def keys(self): 
      return list(self) 

     #the three ratings-related methods 
     def rating(self, key): 
      item = self[key], key 
      i = bisect_left(self._rating, item) 
      if item == self._rating[i]: 
       return i 
      raise LookUpError, "item not found in rating" 

     def getValueByRating(self, rating): 
      return self._rating[rating][0] 

     def getKeyByRating(self, rating): 
      return self._rating[rating][1] 

     def _test(): 
      ''' we use doctest to test this module, which must be named 
      rating.py, by validating all the examples in docstrings. ''' 
      import doctest, rating 
      doctest.testmod(rating) 



if __name__ == "__main__": 

    r = Ratings({"bob":30, "john":30}) 

    print "r is" 
    print r 
    print "\n" 
    print "len(r) is" 
    print len(r) 
    print "\n" 
    print "updating with {'paul': 20, 'tom': 10} " 
    r.update({"paul": 20, "tom": 10}) 
    print "\n" 
    print "now r is" 
    print r 
    print "\n" 
    print "r.has_key('paul') is" 
    print r.has_key("paul") 
    print "\n" 
    print " 'paul' in r is" 
    print ("paul" in r) 
    print "\n" 
    print "r.has_key('alex') is" 
    print r.has_key("alex") 
    print "\n" 
    print " 'alex' in r is" 
    print ("alex" in r) 
    print '\n' 
    print 'r is' 
    print r 
    print "changing john to '20' with 'r['john']= 20' doesn't work. " 
    r["john"]=20 
+0

것입니까? –

+0

저는 2.7을 사용하고 있습니다. 그러나이 책은 파이썬 2.3과 2.4를 대상으로합니다. 그러나이 책의 제 3 판은 파이썬 3을 대상으로합니다. 또한 karthikr은 마지막 몇 가지 방법에 대해 들여 쓰기가 잘못되었다고 지적했습니다. 다른 오류가 발생했습니다. – user2452665

답변

1

문제는 들여 쓰기입니다. 클래스 메소드로 인식 되려면 다음 블록을 한 레벨 왼쪽으로 이동해야합니다.

def __iter__(self): 
     for v, k in self._rating: 
      yield k 
     iterkeys = __iter__ 

    def keys(self): 
     return list(self) 

    #the three ratings-related methods 
    def rating(self, key): 
     item = self[key], key 
     i = bisect_left(self._rating, item) 
     if item == self._rating[i]: 
      return i 
     raise LookUpError, "item not found in rating" 

    def getValueByRating(self, rating): 
     return self._rating[rating][0] 

    def getKeyByRating(self, rating): 
     return self._rating[rating][1] 

    def _test(): 
     ''' we use doctest to test this module, which must be named 
     rating.py, by validating all the examples in docstrings. ''' 
     import doctest, rating 
     doctest.testmod(rating) 
     print "doc test?" 

그래서 클래스는 사용하는 파이썬의 어떤 버전

class Ratings(UserDict.DictMixin, dict): 
    '''The implementation carefully mixes inheritance and delegation 
    to achieve reasonable performance while minimizing boilerplate, 
    and, of course, to ensure semantic correctness as above. All 
    mappings' methods not implemented below get inherited, mostly 
    from DictMixin, but, crucially!, __getitem__ from dict. ''' 

    def __init__(self, *args, **kwds): 
     ''' This class gets instantiated just like 'dict' ''' 
     dict.__init__(self, *args, **kwds) 
     # self._rating is the crucial auxiliary data structure: a list 
     # of all (value, key) pairs, kept in "natural"ly-sorted order 
     self._rating = [ (v, k) for k, v in dict.iteritems(self) ] 
     self._rating.sort() 

    def copy(self): 
     ''' Provide an identical but independent copy ''' 
     return Ratings(self) 

    def __setitem__(self, k, v): 
     ''' besides delegating to dict, we maintain self._rating ''' 
     if k in self: 
      del self._rating[self.rating(k)] ## 
     dict.__setitem__(self, k, v) 
     insort_left(self._rating, (v, k)) 

    def __delitem__(self, k): 
     ''' besides delegating to dict, we maintain self._rating ''' 
     del self._rating[self.rating(k)] 
     dict.__delitem__(self, k) 
     ''' delegate some methods to dict explicitly to avoid getting 
     DictMixin's slower (though correct) implementations instead ''' 
     __len__ = dict.__len__ 
     __contains__ = dict.__contains__ 
     has_key = __contains__ 
     ''' the key semantic connection between self._rating and the order 
     of self.keys() -- DictMixin gives us all other methods 'for 
     free', although we could implement them directly for slightly 
     better performance. ''' 

    def __iter__(self): 
     for v, k in self._rating: 
      yield k 
     iterkeys = __iter__ 

    def keys(self): 
     return list(self) 

    #the three ratings-related methods 
    def rating(self, key): 
     item = self[key], key 
     i = bisect_left(self._rating, item) 
     if item == self._rating[i]: 
      return i 
     raise LookUpError, "item not found in rating" 

    def getValueByRating(self, rating): 
     return self._rating[rating][0] 

    def getKeyByRating(self, rating): 
     return self._rating[rating][1] 

    def _test(): 
     ''' we use doctest to test this module, which must be named 
     rating.py, by validating all the examples in docstrings. ''' 
     import doctest, rating 
     doctest.testmod(rating) 
     print "doc test?" 

if __name__ == "__main__": 

    r = Ratings({"bob":30, "john":30}) 

    print "r is" 
    print r 
    print "\n" 
    print "len(r) is" 
    print len(r) 
    print "\n" 
    print "updating with {'paul': 20, 'tom': 10} " 
    r.update({"paul": 20, "tom": 10}) 
    print "\n" 
    print "now r is" 
    print r 
    print "\n" 
    print "r.has_key('paul') is" 
    print r.has_key("paul") 
    print "\n" 
    print " 'paul' in r is" 
    print ("paul" in r) 
    print "\n" 
    print "r.has_key('alex') is" 
    print r.has_key("alex") 
    print "\n" 
    print " 'alex' in r is" 
    print ("alex" in r) 
    print '\n' 
    print 'r is' 
    print r 
    print "changing john to '20' with 'r['john']= 20' doesn't work. " 
    r["john"]=20 
+0

거룩한 암소! 감사합니다 karthikr. 나는 오랫동안 이것에 대해 꼼짝 않고 바라 보았다. 나는 심지어 더 이상 8에서 4 칸을 식별 할 수 없다. 도움에 감사드립니다. 지금은 코드가 여전히 작동하지 않지만 오류는 새로운 것입니다. 나는 계속 지킬거야. – user2452665