【问题标题】:More Efficient Way of Reading Large List of dicts阅读大量字典的更有效方式
【发布时间】:2013-10-06 13:50:36
【问题描述】:

对于我的项目,我使用 mutagen 库从 5000 多个 mp3 文件中读取 ID3 标签。阅读它们后,我使用它们构造了以下对象。

    class Track:
    def __init__(self, artist, title, album=None):
        self.artist = artist
        self.title = title
        self.album = None

    def __str__(self):
        return "Track: %s : %s" % (self.artist,self.title, )

    def set_album(self,album):
        self.album = album

class Album:
    def __init__(self, artist, title, year='', genre='', tracks=None):
        self.artist = artist
        self.year = year
        self.genre = genre
        self.title = title 
        self.tracks = []

    def __str__(self):
        return "Album: %s : %s [%d]" % (self.artist,self.title,len(self.tracks))

    def add_track(self,track):
        self.tracks.append(track)

问题是某些文件缺少一些必需的标签(缺少标题、缺少艺术家或两者兼有),导致 KeyValueError

 #'TALB' (album title), 'TIT2' (track title), 'TPE1' (artist), 'TDRC' (year), and 'TCON' (genre)
    for root, dirs, files in os.walk(dir):
        for filename in files:
            if filename.lower().endswith(e):
                fullname = os.path.join(root, filename)
                try:
                    audio = mutagen.File(fullname)
                    track = Track(audio['TPE1'],audio['TIT2'])
                    album = Album(audio['TPE1'], audio['TALB'], audio['TDRC'], audio['TCON'])
                excpet Exception as e:
                                print "Error on %s. %s " % (filename,type(e).__name__)  

这会加载具有所有标签的所有文件,这还不够好。 我通过使用 ifs 解决了这个问题,它工作正常并且速度足够快。但是我想知道是否有更好的方法来处理这个问题。

【问题讨论】:

  • dic.get(key) 比较慢
  • 如何总结dic.get(key) is slower
  • 可能有更好的方法来实现您的愿望,但由于您没有给我们提供任何背景信息,所以这个问题是不完整的。例如process(data) 完全独立于未设置哪些键。
  • 我编辑了这个问题,以准确说明我想要做什么。下次我问优化相关问题时,我一定会提供更多上下文。

标签: python optimization data-structures dictionary mutagen


【解决方案1】:

如果您的 default 值可以是空字符串而不是 None,则可以使用 defaultdict。

>>> 
>>> from collections import defaultdict
>>> d = defaultdict(str)
>>> d['a'] = 'data'
>>> d['b'] = 1
>>> d
defaultdict(<type 'str'>, {'a': 'data', 'b': 1})
>>> a = d['a']
>>> b = d['b']
>>> c = d['c']
>>> a, b, c
('data', 1, '')
>>> d
defaultdict(<type 'str'>, {'a': 'data', 'c': '', 'b': 1})
>>> 

【讨论】:

  • 或者如果你需要默认为无,quick search 想出了这个显而易见的解决方案d = defaultdict(lambda: None)
【解决方案2】:

是的,使用dict.get()

process(data.get('a'), data.get('b'), data.get('c'), data.get('d'))

这类似于dict[key],除了不是引发KeyError,而是return None,或者它可以返回传递的第二个参数(默认为None)。

类似于:

try:
    blah = data['a']
except ValueError:
    blah = None

或者:

if 'a' in data:
    blah = data['a']
else:
    blah = None

【讨论】:

  • 它与其中一个相似吗?它们具有截然不同的性能特征。
【解决方案3】:

使用data.get("a") - 如果a 作为data 中的键存在,这将返回data["a"] 的值,否则将返回None

【讨论】:

    【解决方案4】:

    你的陈述

    a = data['a'] if 'a' in key else None
    

    相当于这个更简洁(也更高效)的语句:

    a = data.get('a')
    

    您也可以考虑将data 传递给process

    process(data)
    

    最后,还有一些“巧妙”的方法可以做到这一点,这里可能不保证,但是这些方面的东西可能会为您服务:

    process(**data)
    

    【讨论】:

    • process(**data) 并不完全相同。相当于process(a='data', b='data'
    • 是的。不一样,但(可能)对于 OP 正在做的事情更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-30
    • 1970-01-01
    • 2016-02-10
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多