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)
有几个人指出 **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)
所以下面的代码会返回 'Unknown notAKey'。
k = Song()
print k.format('{notAKey}')
5 个回答
1
不幸的是,当你用 **foo
这种写法调用一个方法时,它会把 foo
转换成一个普通的字典。最简单的解决办法可能就是你在第一个代码片段中提到的那个。
3
警告:这个解决方案实际上并不能解决关于
'{title} - {artist}'.format(**default)
的原始问题。
你有没有试过从 collections
导入 defaultdict
呢?
from collections import defaultdict
class Song(defaultdict):
def __missing__(self, key):
return 'Unknown {key}'.format(key = key)
这里有一个类似的问题:如何创建一个 Python 字典,使得当字典中缺少某个键时返回该键,而不是抛出 KeyError 错误?:
6
总结: 把歌曲封装到一个类里。
在我看来,歌曲在你的代码中就像一种基本的数据类型,值得专门用一个类来表示。你可以在这个类内部使用字典来存储数据,但尽量让这个类的抽象层次高于简单的字典。
你应该让这个类提供所有支持你对歌曲进行操作的服务。把所有格式化的代码放在这个类里,这样就不会在使用歌曲的代码中到处乱散。实际上,你会发现有很多操作都可以变成这个类的方法。
至于格式化的实现,虽然可能会写得有点长,但没关系,因为你只需要在一个地方写它。