代码之家  ›  专栏  ›  技术社区  ›  user2452665

Python食谱

  •  0
  • user2452665  · 技术社区  · 13 年前

    我正在尝试实现O'Reilly的Python Cookbook(第二版)中的一个食谱,但其中一小部分没有起到应有的作用。我希望有人能帮我找出原因。

    食谱是“5.14:用评级功能增强字典类型”。我已经完成了大部分代码,但在试图更改键的“排名”时出错。我在所有的评论中都留下了作者的评论,这样任何试图提供帮助的人都会很清楚“内裤”和“内裤”是干什么的。尤其是“评级”方面,我认为这是导致错误的原因。

    错误:

    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'
    

    代码:

    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
    
    1 回复  |  直到 13 年前
        1
  •  1
  •   karthikr    13 年前

    你的问题是缩进。您必须将下面的块向左移动一级,才能将它们识别为类方法。

        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