长话短说,我想用任意命名的参数调用格式,这将形成一个查找。
'{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__
实施为return True
,但仍然KeyError
。
所以**
似乎不只是在传入的对象上调用__getitem__
。有人知道怎么解决这个问题吗?
答案 0 :(得分: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
需要3个参数:格式字符串,位置字段序列和关键字字段的映射。由于不需要位置字段,我使用了空元组()
。
答案 1 :(得分:5)
Python 3.2 +:
'{Thing1} and {other_thing}'.format_map(my_mapping)
答案 2 :(得分:2)
这可能有点神秘,但我最近遇到了这个问题,这个问题是第一个结果。我对使用string.Formatter
感到不满意,并希望 Just Work (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']
答案 3 :(得分:1)
这是我能想到的最好的:
如果你有一个自定义映射对象要传递给一个带有关键字参数的func,那么它必须有一组键(可以动态生成,但它必须是有限集),并且它必须能够以某种方式映射这些键。因此,如果您可以假设它将获得__iter__
来获取密钥,并且__getitem__
将成功获得每个密钥,例如:
class Me(object):
def __init__(self):
pass
def __iter__(self):
return iter(['a', 'b', 'c'])
def __getitem__(self, key):
return 12
说功能是:
def myfunc(**kwargs):
print kwargs, type(kwargs)
然后我们可以通过制作一个词典来传递它:
m = Me()
myfunc(**dict((k, m[k]) for k in m))
导致:
{'a': 12, 'c': 12, 'b': 12} <type 'dict'>
显然这必须是它完成的方式......即使你传入一个派生自dict
的对象,该函数仍然会有一个dict
的kwargs:
class Me(dict): pass
m = Me()
print type(m) #prints <class '__Main__.Me'>
def myfunc(**kwargs):
print type(kwargs)
myfunc(**m) #prints <type 'dict'>
因为听起来你想要做一些事情,比如根据键是什么来返回一个值,没有特定的键集,似乎你不能使用format
函数。