我正在尝试执行以下操作:解析我的音乐文件夹中的所有文件,如果它们是我的收藏夹,请将它们复制到单独的文件夹中。
为了达到这个目的,我正在用我喜爱的曲目解析一个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文件时,我得到dictionary Key Error。我在这里找到了一个潜在的答案:How to make a python dictionary that returns key for keys missing from the dictionary instead of raising 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?
P.S。我想我应该提到我是python的新手,只有几个小时的“经验”,这是我尝试学习语言的方式。
答案 0 :(得分: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
答案 1 :(得分:1)
您可以尝试的一件事是使用defaultdict
,参数为defaultdict(dict)
。无论何时尝试引用不存在的值,它都不会抛出错误,而是返回您指定的默认空值:
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
(因为{ {1}}是整数的空值)。如果我们使用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'
,我们必须做一些诡计:因为defaultdict
的参数需要可调用(但不是然后调用 - &gt;请参阅defaultdict
与int
),我们使用int()
函数来模拟此行为。在一个非常简单的层面上,将lambda
视为阻止在需要之前调用lambda
。现在,您将拥有一个字典(带有嵌套字典),可以处理两层深度的缺失键,而不会抛出错误。希望能解释一下。