我知道可以扩展 Formatter 以提供 PEP3101 中讨论的其他表示类型,但这对于我的需求来说太慢了。我很好奇其他一些选项可能用于为字符串注入自定义表示类型。
目前,唯一想到的其他选项是检查字符串的 {vars},记下表示类型和索引,去除自定义表示类型、格式,然后根据我的需要发布结果格式。
在利用格式速度的同时,还有其他选择可以避免后处理吗?
我制定了一个似乎在 cython 中开销显着减少的解决方案,尽管在 python 中也可以这样做,并且在这里提供示例(不确定开销)。
根据 python 文档,对象可以实现 __ format__ 方法并接收格式规范。在 cython 中,我实现了我自己的 uobj 类型,它充当传递给 str.format 的 args 和 kwargs 的泛型。python 中的相同内容(作为转义 < 和 > 的通用示例)看起来像这样。
class uobj:
def __init__(self, obj):
self.obj = obj
def __format__(self, format_spec):
if format_spec == 's':
return str(self.obj)
else:
# edit, shoehorning this in for completeness
# to call an original format spec as should probably
# happen after you do your own processing, use __format__
if isinstance(self.obj, (int, float)):
return self.obj.__format__(format_spec)
# so then a :.2f spec on uobj(123.456) would work as expected
return str(self.obj).replace('<', '<').replace('>', '>')
def __getitem__(self, key):
return uobj(self.obj[key])
所以现在,uobj 可以存储一个用户对象(以下示例中的 str 或 dict),然后可以像这样访问
d = uobj({'a': '<b>asdf'})
s = uobj('<span>qwer</span>')
'{0:s} {d[a]}'.format(s, d=d)
# ouputs: '<span>qwer</span><asdf'
并且在 *args 和 **kwargs 上的 fmt 函数内部会发生对 uobj 的强制转换。这里还有更多细节需要解决,例如我注意到 ints 在我的单元测试中无法解析,并且 uobj 需要通过 *uobj 和 **uobj 解包才能按需转换对象,尽管我可能需要将其分解为列表和字典的相应克隆。不过,这对我来说似乎是最好的道路。
编辑
似乎生病在这里阅读模拟容器类型 http://docs.python.org/reference/datamodel.html#emulating-container-types