我可以使用动态映射解包Python中的关键字参数吗?

6 投票
4 回答
2647 浏览
提问于 2025-04-17 06:47

长话短说,我想用任意名称的参数来调用格式化函数,这样可以进行查找。

'{Thing1} and {other_thing}'.format(**my_mapping)

我尝试像这样实现我的映射(my_mapping):

class Mapping(object):
  def __getitem__(self, key):
    return 'Proxied: %s' % key
my_mapping = Mapping()

当我调用 my_mapping['anything'] 时,它的表现是正常的。但是当我像上面那样把它传给格式化函数(format())时,我得到了:

TypeError: format() argument after ** must be a mapping, not Mapping

我试着用 dict 来继承,而不是用 object,但是现在像上面那样调用 format() 时却出现了 KeyError 错误。我甚至实现了 __contains__ 方法,让它总是返回真(True),但还是出现了 KeyError

所以看起来 ** 不是简单地在传入的对象上调用 __getitem__ 方法。有没有人知道该怎么解决这个问题?

4 个回答

2

这可能有点像复活死去的内容,但我最近遇到了这个问题,而这个StackOverflow的问题是我找到的第一个结果。我对使用 string.Formatter 不太满意,想要它能够直接工作 (TM)

如果你为你的类实现一个 keys() 函数和 __getitem__() 方法,那么 **my_mapping 就能正常工作。

也就是说:

class Mapping(object):

  def __getitem__(self, key):
    return 'Proxied: %s' % key

  def keys(self):
    return proxy.keys()

在这里

>>> my_mapping = Mapping()
>>> my_mapping.keys()
['Thing1','other_thing',...,'Thing2']

将会得到一个成功的映射,可以与 .format 一起使用。

显然(虽然我并没有实际查看 str.format 的源代码),它似乎是使用 keys() 来获取一个键的列表,然后将字符串中给出的标识符映射到这些键上,最后使用 __getitem__() 来获取指定的值。

希望这对你有帮助。

编辑

如果你处于 @aaron-mcmillin 的情况,并且键的集合很大,那么一个可能的方法是不要生成完整的键集,而是生成一个较小的子集。当然,这只有在你知道只需要格式化一个小子集时才有效。

也就是说:

class Mapping(object):
  ...
  def keys(self):
    return ['Thing1','other_thing', 'Thing2']
5

Python 3.2及以上版本:

'{Thing1} and {other_thing}'.format_map(my_mapping)
6

在Python 2中,你可以使用 string.Formatter 类来做到这一点。

>>> class Mapping(object):
...     def __getitem__(self, key):
...         return 'Proxied: %s' % key
...
>>> my_mapping = Mapping()
>>> from string import Formatter
>>> Formatter().vformat('{Thing1} and {other_thing}', (), my_mapping)
'Proxied: Thing1 and Proxied: other_thing'
>>>

vformat 这个函数需要三个参数:格式字符串、位置字段的序列和关键字字段的映射。因为不需要位置字段,所以我用了一个空的元组 ()

撰写回答