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ファイルを実行しようとすると、辞書のキーエラーが発生します。私はここで潜在的な答えを見つけました:KeyErrorを発生させる代わりに辞書から欠落しているキーのキーを返すPython辞書を作成するにはどうすればよいですか?以下のように適用しましたが、それでもキーエラーが発生しました

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

最善の解決策は何でしょうか?単純なifの代わりにtry/exceptを使用しますか?

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

試すことができることの1つはdefaultdict、引数を。として使用することです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これは、値が見つからない場合、エラーをスローする代わりに、 (整数のnull値であるため)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'

したがって、ネストされた辞書をdefaultdict同様にするには、少し注意が必要です。への引数defaultdictは呼び出し可能である必要があるものであるため(ただし、まだ呼び出されていません->参照intvs. int())、lambda関数を使用しますこの動作をいくらかシミュレートします。非常に単純なレベルでは、が必要になるまで呼び出されlambdaないようにすることと考えてください。defaultdict(dict)これで、エラーをスローせずに2レベルの深さで欠落しているキーを処理するディクショナリ(ネストされたディクショナリを含む)が作成されます。それが少し説明することを願っています。

于 2012-11-24T19:41:42.593 に答える