2011-08-19 137 views
5

最近我已经做了很多基础的音乐节目,并因此发现自己做这种事情很多应对一些歌曲丢失的元数据:字符串在python格式化

default = {'title': 'Unknown title', 'artist': 'unknown Artist'} 
default.update(song) 
print '{title} - {artist}'.format(**default) 

有一个更清洁的方式来做到这一点我试图重写__missing__像这样,但丢失的钥匙仍然抛出KeyError异常:

class Song(dict): 
    # dictionary with some nice stuff to make it nicer 

    def __missing__(self, key): 
     return 'Unknown {key}'.format(key = key) 

编辑:对不起,我应该已经明朗,基本上下面的必须工作。

s = Song() 
print '{notAKey}'.format(s) 

有几个人指出**不是必需的。

编辑2:我解决了我的问题,至少让我满意。这是否清洁是值得商榷的,但对我来说却很有用。

from string import Formatter 

class DefaultFormatter(Formatter): 

    def get_value(self, key, args, kwargs): 
     # Try standard formatting, then return 'unknown key' 

     try: 
      return Formatter.get_value(self, key, args, kwargs) 
     except KeyError: 
      return kwargs.get(key, 'Unknown {0}'.format(key)) 

class Song(dict): 

    def format(self, formatString): 
     # Convenience method, create a DefaultFormatter and use it 

     f = DefaultFormatter() 
     return f.format(formatString, **self) 

所以下面将返回 '未知notAKey'

k = Song() 
print k.format('{notAKey}') 
+0

只是一个小建议:似乎,你正在做日常使用的应用程序,也许分发它。如果你愿意,那么你应该开始使用[gettext](http://docs.python.org/library/gettext.html) - 你将在以后节省很多麻烦。 – nagisa

回答

-1

我更喜欢Jared的版本,但如果你真的想实现它自己,这里是一个办法:

>>> class Song(dict): 
...  def __getitem__(self, key): 
...    if key in self.keys(): return super(Song, self).__getitem__(key) 
...    return 'Unknown {key}'.format(key=key) 
... 
>>> s = Song() 
>>> s['foo'] 
'Unknown foo' 
>>> s['foo'] = 1 
>>> s['foo'] 
1 
+0

+1显示如何自己实现它,如果你需要进一步的定制。 –

+0

'self.keys()'中的键将O(1)操作变成O(n)。另外,换行符是免费的。 – habnabit

+0

这**不起作用**,因为** ** foo'将传递的东西转换成正常的字典。你是否根据实际情况对它进行了测试? –

3

Warning: This solution does not actually work to solve the original question regarding '{title} - {artist}'.format(**default)

您是否试图从collections导入defaultdict

from collections import defaultdict 

class Song(defaultdict): 
    def __missing__(self, key): 
     return 'Unknown {key}'.format(key = key) 

这里有一个类似的问题:How to make a python dictionary that returns key for keys missing from the dictionary instead of raising KeyError?

+0

这个**不起作用**出于同样的原因OP的第二个片段不起作用。我不知道你为什么相信它会起作用。你在通过'** your_instance'的时候测试了它吗? –

-1

那么,一个选择,我能想到的是使用本质上可以为您提供的默认值,即getattr的方法。如果你想改变你的字典为对象转向钥匙落入属性,你可以使用安全getattr中检索值:

class AttributeDict(): 
    def __init__(self, source_dict): 
     self._ATTRIBUTE_DICT_source_dict = source_dict 
     for key in source_dict.keys(): 
      setattr(self, str(key), source_dict[key]) 

现在,你可以简单地使用:

song = AttributeDict(song) 
artist = getattr(song, 'artist', 'Unknown Artist') 
6

摘要:将该歌曲封装在一个类中。

这听起来像一首歌是你的代码中的主要数据类型,值得有一个专门的类来表示它。通过一切手段使用类内部的字典来存储数据,但尝试和移动到一个更高的抽象层次比字典。

您应该为此班级提供所需的所有服务,以支持您在歌曲上执行的操作。放置课程中的所有格式化代码,以便它不会分散使用歌曲项目的代码。事实上,你会发现各种想要成为这个类的方法的操作。

至于格式化的实现,它是否有点冗长,因为你只写在一个地方。

1

不幸的是,当您使用**foo语法调用方法时,它将foo转换为正规字典。最干净的解决方案可能是您在第一个片段中发布的解决方案。

+0

好点。我更喜欢第一课。 – leoluk