Python中使用.itemgetter对列表值排序的奇怪输出

1 投票
1 回答
978 浏览
提问于 2025-04-17 14:02

我正在参加谷歌的Python编程课程,现在在做一个叫Word_Count.py的练习。这个练习的目标是创建一个字典,字典的键是单词,值是单词的出现次数,并把它们以元组的形式返回,以便打印出来。

我已经写了一个辅助函数来创建这个字典:

def dict_creator(filename): #helper function to create a dictionary each 'word' is a key and the 'wordcount' is the value
            input_file = open(filename, 'r') #open file as read
            for line in input_file: #for each line of text in the input file
                    words = line.split() #split each line into individual words
                    for word in words: #for each word in the words list(?)
                            word = word.lower() #make each word lower case.
                            if word not in word_count: #if the word hasn't been seen before
                                    word_count[word] = 1 #create a dictionary key with the 'word' and assign a value of 1
                            else: word_count[word] += 1 #if 'word' seen before, increase value by 1
            return word_count #return word_count dictionary
            word_count.close()

现在我正在使用这个帖子中提到的.itemgetter方法,来创建一个按值(出现次数)从大到小排序的字典:链接。这是我的代码:

def print_words(filename):
        word_count = dict_creator(filename) #run dict_creator on input file (creating dictionary)
        print sorted(word_count.iteritems(), key=operator.itemgetter(1), reverse=True)
        #print dictionary in total sorted descending by value. Values have been doubled compared to original dictionary?
        for word in sorted(word_count.iteritems(), key=operator.itemgetter(1), reverse=True):
                #create sorted list of tuples using operator module functions sorted in an inverse manner
                a = word
                b = word_count[word]
                print a, b #print key and value

但是,当我在测试文件和一个较小的文件上运行代码时,出现了一个键错误(如下所示)。

Traceback (most recent call last):
  File "F:\Misc\google-python-exercises\basic\wordcount_edited.py", line 74, in <module>
    print_words(lorem_ipsum) #run input file through print_words
  File "F:\Misc\google-python-exercises\basic\wordcount_edited.py", line 70, in print_words
    b = word_count[word]
KeyError: ('in', 3)

我打印了原始字典和排序后的字典,发现排序后字典中的所有值都翻倍了。我查看了几个相关的讨论串,并检查了.itemgetter的文档,但似乎没有找到其他人有类似的问题。

有没有人能指出是什么原因导致我的代码在word_count函数中第二次遍历字典,从而导致值增加?

谢谢!

SB

1 个回答

1

(1) 你在 dict_creator 里其实并没有定义 word_count。我原本期待在开头看到

word_count = {}

这段代码。这意味着你所改变的 word_count 是在别的地方定义的,并且是全局的,所以每次你调用 dict_creator 时,它都会往同一个 word_count 字典里添加内容,增加值。根据你展示的代码,你只有一个 word_count

(2) 关于 KeyError 的问题:

   for word in sorted(word_count.iteritems(), key=operator.itemgetter(1), reverse=True):
            #create sorted list of tuples using operator module functions sorted in an inverse manner
            a = word
            b = word_count[word]

iteritems() 返回的是元组,所以 word 实际上已经是类似 ('dict_creator', 1) 这样的东西了。你可以直接打印它。调用 word_count[word] 是在尝试用这个元组 (key, value) 作为键。换句话说,虽然你把变量叫做 word,但它实际上是 word_and_count,其中 word, count = word_and_count

(3) 在这一部分:

        return word_count #return word_count dictionary
        word_count.close()

我觉得你是想说 input_file.close(),但是在你返回之后再关闭文件是没有意义的,因为那行代码不会被执行。另一种选择是使用 with 这个写法:

with open(filename) as input_file:
    code_goes_here = True
return word_count

这样文件会自动关闭。

在做了上述修改后,你的代码对我来说似乎可以正常工作。

撰写回答