Python食谱中的配方

Python食谱中的配方,python,dictionary,sorted,cookbook,Python,Dictionary,Sorted,Cookbook,我试图实现O'Reilly的Python食谱(第二版)中的一个菜谱,但菜谱中的一小部分没有发挥应有的作用。我希望有人能帮我找出原因 诀窍是“5.14:通过评级功能增强字典类型”。我已经完成了大部分代码,但在尝试更改键的“排名”时出错。我在所有的评论中都留下了作者的评论,因此任何试图帮助我的人都会对“unders”和“dunders”的用途有一个很好的了解。尤其是“U评级”方面,我认为这是造成错误的原因 错误: File "rating.py", line 119, in <module&g

我试图实现O'Reilly的Python食谱(第二版)中的一个菜谱,但菜谱中的一小部分没有发挥应有的作用。我希望有人能帮我找出原因

诀窍是“5.14:通过评级功能增强字典类型”。我已经完成了大部分代码,但在尝试更改键的“排名”时出错。我在所有的评论中都留下了作者的评论,因此任何试图帮助我的人都会对“unders”和“dunders”的用途有一个很好的了解。尤其是“U评级”方面,我认为这是造成错误的原因

错误:

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'

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

    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

您使用的是哪个版本的Python?我使用的是2.7,但我知道这本书是针对Python 2.3和2.4的。然而,本书的第三版是针对Python3的。此外,karthikr指出,我的缩进在最后几个方法中是错误的-这是真的。我现在又犯了其他错误。天哪!谢谢你,卡提克。我盯着这个看了这么久,我甚至不能再从8中分辨出4个空格。我感谢你的帮助。目前,代码仍然不起作用,但错误是新的。我会坚持下去的。
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