dictionary - Recipe from Python Cookbook -
i'm trying implement recipe o'reilly's python cookbook (2nd ed.) , small portion of recipe doesn't work should. hoping me figure out why.
the recipe "5.14: enhancing dictionary type ratings functionality." i've got of code working, error when trying change 'ranking' of key. i've left in comments author's trying have idea "unders" , "dunders" for. "_rating" aspect, believe somehow causing error.
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 mixes inheritance , delegation achieve reasonable performance while minimizing boilerplate, and, of course, ensure semantic correctness above. mappings' methods not implemented below inherited, dictmixin, but, crucially!, __getitem__ dict. ''' def __init__(self, *args, **kwds): ''' class gets instantiated 'dict' ''' dict.__init__(self, *args, **kwds) # self._rating crucial auxiliary data structure: list # of (value, key) pairs, kept in "natural"ly-sorted order self._rating = [ (v, k) k, v in dict.iteritems(self) ] self._rating.sort() def copy(self): ''' provide identical independent copy ''' return ratings(self) def __setitem__(self, k, v): ''' besides delegating dict, 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 dict, maintain self._rating ''' del self._rating[self.rating(k)] dict.__delitem__(self, k) ''' delegate methods dict explicitly avoid getting dictmixin's slower (though correct) implementations instead ''' __len__ = dict.__len__ __contains__ = dict.__contains__ has_key = __contains__ ''' key semantic connection between self._rating , order of self.keys( ) -- dictmixin gives other methods 'for free', although implement them directly better performance. ''' def __iter__(self): v, k in self._rating: yield k iterkeys = __iter__ def keys(self): return list(self) #the 3 ratings-related methods def rating(self, key): item = self[key], key = bisect_left(self._rating, item) if item == self._rating[i]: return 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( ): ''' use doctest test module, must named rating.py, validating 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 {'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 '20' 'r['john']= 20' doesn't work. " r["john"]=20
your issue indentation. have move following block 1 level left them recognized class methods.
def __iter__(self): v, k in self._rating: yield k iterkeys = __iter__ def keys(self): return list(self) #the 3 ratings-related methods def rating(self, key): item = self[key], key = bisect_left(self._rating, item) if item == self._rating[i]: return 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( ): ''' use doctest test module, must named rating.py, validating examples in docstrings. ''' import doctest, rating doctest.testmod(rating) print "doc test?"
so class be
class ratings(userdict.dictmixin, dict): '''the implementation mixes inheritance , delegation achieve reasonable performance while minimizing boilerplate, and, of course, ensure semantic correctness above. mappings' methods not implemented below inherited, dictmixin, but, crucially!, __getitem__ dict. ''' def __init__(self, *args, **kwds): ''' class gets instantiated 'dict' ''' dict.__init__(self, *args, **kwds) # self._rating crucial auxiliary data structure: list # of (value, key) pairs, kept in "natural"ly-sorted order self._rating = [ (v, k) k, v in dict.iteritems(self) ] self._rating.sort() def copy(self): ''' provide identical independent copy ''' return ratings(self) def __setitem__(self, k, v): ''' besides delegating dict, 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 dict, maintain self._rating ''' del self._rating[self.rating(k)] dict.__delitem__(self, k) ''' delegate methods dict explicitly avoid getting dictmixin's slower (though correct) implementations instead ''' __len__ = dict.__len__ __contains__ = dict.__contains__ has_key = __contains__ ''' key semantic connection between self._rating , order of self.keys( ) -- dictmixin gives other methods 'for free', although implement them directly better performance. ''' def __iter__(self): v, k in self._rating: yield k iterkeys = __iter__ def keys(self): return list(self) #the 3 ratings-related methods def rating(self, key): item = self[key], key = bisect_left(self._rating, item) if item == self._rating[i]: return 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( ): ''' use doctest test module, must named rating.py, validating 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 {'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 '20' 'r['john']= 20' doesn't work. " r["john"]=20
Comments
Post a Comment