"{}, {}, {}".format(*(1,2,3,4,5))
打印:
'1, 2, 3'
只要 format
中的 {}
的数量不超过元组的长度,它就可以工作。我想让它适用于任意长度的元组,如果长度不足,则用 -
填充它。为了避免对 {}
的数量做出假设,我想使用生成器。这是我的想法:
def tup(*args):
for s in itertools.chain(args, itertools.repeat('-')):
yield s
print "{}, {}, {}".format(*tup(1,2))
预期:
'1, 2, -'
但它永远不会回来。你能让它与发电机一起工作吗?有没有更好的方法?
最佳答案
如果您考虑一下,除了变量参数解包是一次解包之外,还有一个事实是 format
不一定按顺序获取其参数,如 ' {2} {1} {0}'
。
如果 format
只是采用一个序列而不需要单独的参数,您可以通过构建一个做正确事情的序列来解决这个问题。这是一个简单的例子:
class DefaultList(list):
def __getitem__(self, idx):
try:
return super(DefaultList, self).__getitem__(idx)
except IndexError:
return '-'
当然,您的真实版本会包装任意可迭代对象,而不是 list
的子类,并且可能必须使用 tee
或内部缓存并引入新值按照要求,只有在你结束时才默认。 (您可能想在 ActiveState 上搜索“惰性列表”或“惰性序列”食谱,因为它们中有一些是这样做的。)但这足以说明示例。
现在,这对我们有什么帮助?它没有; *lst
on a DefaultList
将尝试从事物中创建一个元组,为我们提供与我们已经拥有的参数数量完全相同的参数。但是,如果您有一个版本的 format
可以取而代之的是一系列 args 呢?然后你可以传递你的 DefaultList
就可以了。
你确实有:Formatter.vformat
.
>>> string.Formatter().vformat('{0} {1} {2}', DefaultList([0, 1]), {})
'0 1 -'
但是,还有一种更简单的方法,一旦您显式使用 Formatter
而不是通过 str
方法隐式使用。您可以覆盖它的 get_value
方法和/或其 check_unused_args
:
class DefaultFormatter(string.Formatter):
def __init__(self, default):
self.default = default
# Allow excess arguments
def check_unused_args(self, used_args, args, kwargs):
pass
# Fill in missing arguments
def get_value(self, key, args, kwargs):
try:
return super(DefaultFormatter, self).get_value(key, args, kwargs)
except IndexError:
return '-'
f = DefaultFormatter('-')
print(f.vformat('{0} {2}', [0], {}))
print(f.vformat('{0} {2}', [0, 1, 2, 3], {}))
当然,您仍然需要将迭代器包装在提供 Sequence 协议(protocol)的东西中。
当我们这样做时,如果该语言具有“可迭代解包”协议(protocol),则可以更直接地解决您的问题。参见 here对于提出这样的事情的 python-ideas 线程,以及该想法存在的所有问题。 (另请注意,format
函数会使这更棘手,因为它必须直接使用解包协议(protocol),而不是依赖解释器神奇地完成它。但是,假设它这样做了,那么你d 只需要为处理 __unpack__
的任何可迭代对象编写一个非常简单且通用的包装器。)
关于python - 生成器可以在 python 中与 string.format 一起使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18472436/