0

我正在尝试做以下事情:解析我的音乐文件夹中的所有文件,如果它们是我的最爱,请将它们复制到单独的文件夹中。

为了实现这一点,我正在用我喜欢的曲目解析一个 xml,并使用这些信息来创建一个像这样结构的自定义字典

lovedSongs[artist][title] = 1

当我从我的文件夹中解析文件时,我从 id3 标签中读取了歌曲标题和艺术家,理论上,我尝试查看是否lovedSongs[tagArtist][tagTitle]为 1

for filename in filelist:     
        if filename[-4:] == ".mp3":
            try:
                id3r = id3reader.Reader(filename)
            except UnicodeDecodeError:
                artist = "None"
                title = "None"
            except IOError:
                artist = "None"
                title = "None"
            else:
                artist = ensureutf8andstring(id3r.getValue('performer'))
                title = ensureutf8andstring(id3r.getValue('title'))

            if artist != "None" or title != "None":
                if lovedSongs[artist][title] == 1:
                    print artist + ' - ' + title

当我尝试运行 .py 文件时,我得到一个字典 Key Error。我在这里找到了一个潜在的答案:How to make a python dictionary that return key for keys missing from the dictionary 而不是引发 KeyError?并像下面一样应用它,但我仍然得到关键错误

class SongDict(dict):
    def __init__(self, default=None):
        self.default = default

    def __getitem__(self, key):
        if not self.has_key(key):
            self[key] = self.default()
        return dict.__getitem__(self, key)

    def __missing__(self, key):
        return 0

最好的解决方案是什么?使用 try/except 来代替简单的 if?

PS我想我应该提到我是python的新手,只有几个小时的“经验”,这是我尝试学习语言的方式。

4

2 回答 2

2

听起来你真正想要的是一个简单的set

for filename in filelist:     
    if filename.endswith(".mp3"):
        try:
            id3r = id3reader.Reader(filename)
        except (UnicodeDecodeError, IOError):
            pass
        else:
            artist = ensureutf8andstring(id3r.getValue('performer'))
            title = ensureutf8andstring(id3r.getValue('title'))

            if artist != "None" or title != "None":
                if (artist, title) in lovedSongs:
                    print artist + ' - ' + title
于 2012-11-24T19:39:57.520 回答
1

您可以尝试的一件事是使用 a defaultdict,参数是 a defaultdict(dict)。每当您尝试引用不存在的值时,它都不会引发错误,而是会返回您指定的默认 null 值:

In [7]: from collections import defaultdict

In [8]: lovedsongs = defaultdict(lambda: defaultdict(dict))

In [9]: lovedsongs['OAR']['Blackrock'] = 1

In [10]: lovedsongs['Timati']['Moj Put'] = 1

In [11]: lovedsongs
Out[11]: defaultdict(<function <lambda> at 0x24e5ed8>, {'Timati': defaultdict(<type 'dict'>, {'Moj Put': 1}), 'OAR': defaultdict(<type 'dict'>, {'Blackrock': 1})})

In [12]: lovedsongs['Not']['Found']
Out[12]: {}

In [13]: if lovedsongs['Not']['Found'] == 1:
   ....:     print 'Found it'
   ....:
   ....:

In [14]: if lovedsongs['OAR']['Blackrock'] == 1:
   ....:     print 'Found it'
   ....:
   ....:
Found it

通过defaultdict(lambda: defaultdict(dict))查看单级(即“更常规”)的defaultdict工作方式,可能会更好地理解语法:

In [1]: from collections import defaultdict

In [2]: d = defaultdict(int)

In [3]: d['one'] = 1

In [4]: d['two'] = 2

In [5]: d
Out[5]: defaultdict(<type 'int'>, {'two': 2, 'one': 1})

In [6]: d['one']
Out[6]: 1

In [7]: d['three']
Out[7]: 0

我们defaultdict用参数声明了int- 这意味着如果没有找到一个值,而不是抛出错误,我们只会0返回(因为0是整数的空值)。如果我们使用str,我们会''回来,如果我们使用dict,我们会得到一本字典。然而,在这种情况下,棘手的部分是您有一个嵌套字典 ( defaultdict(dict)),如果您尝试引用嵌套字典中不存在的键,则会遇到同样的问题:

In [13]: d = defaultdict(dict)

In [14]: d['three']['more']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)

/path/<ipython console> in <module>()

KeyError: 'more'

所以为了让我们的嵌套字典也变成 a defaultdict,我们必须做一些小把戏:因为 to 的参数defaultdict是需要可调用的(但尚未调用 -> 参见intvs. int()),我们使用一个lambda函数在某种程度上模拟这种行为。在一个非常简单的级别上,将lambda视为防止在defaultdict(dict)需要时调用 。现在您将拥有一个字典(带有嵌套字典),它将处理两级深度的缺失键而不会引发错误。希望能解释一下。

于 2012-11-24T19:41:42.593 回答