Python中的字符串格式化

5 投票
5 回答
4100 浏览
提问于 2025-04-16 23:58

最近我一直在做与音乐相关的编程,因此我经常需要处理一些歌曲中缺失的元数据(就是一些描述歌曲的信息)。

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

总结: 把歌曲封装到一个类里。

在我看来,歌曲在你的代码中就像一种基本的数据类型,值得专门用一个类来表示。你可以在这个类内部使用字典来存储数据,但尽量让这个类的抽象层次高于简单的字典。

你应该让这个类提供所有支持你对歌曲进行操作的服务。把所有格式化的代码放在这个类里,这样就不会在使用歌曲的代码中到处乱散。实际上,你会发现有很多操作都可以变成这个类的方法。

至于格式化的实现,虽然可能会写得有点长,但没关系,因为你只需要在一个地方写它。

撰写回答