use*_*854 6 python string format generator
"{}, {}, {}".format(*(1,2,3,4,5))
Run Code Online (Sandbox Code Playgroud)
打印:
'1, 2, 3'
Run Code Online (Sandbox Code Playgroud)
这个工作原理,只要{}in 的数量format不超过元组的长度.我想让它适用于任意长度的元组,-如果长度不足则用s 填充它.为了避免对数量进行假设{},我想使用一台发电机.这就是我的想法:
def tup(*args):
for s in itertools.chain(args, itertools.repeat('-')):
yield s
print "{}, {}, {}".format(*tup(1,2))
Run Code Online (Sandbox Code Playgroud)
预期:
'1, 2, -'
Run Code Online (Sandbox Code Playgroud)
但它永远不会回归.你能用发电机吗?有更好的方法吗?
如果您考虑一下,除了变量参数解包会立即解包这一事实之外,还有一个事实是format不一定按顺序获取其参数,如'{2} {1} {0}'.
如果format只采用一个序列而不需要单独的参数,通过构建一个执行正确操作的序列,您可以解决此问题。这是一个简单的例子:
class DefaultList(list):
def __getitem__(self, idx):
try:
return super(DefaultList, self).__getitem__(idx)
except IndexError:
return '-'
Run Code Online (Sandbox Code Playgroud)
当然,您的现实生活版本将包装任意可迭代对象,而不是 subclass list,并且可能必须使用tee内部缓存并根据请求提取新值,仅在您通过末尾时才默认。(您可能想要在 ActiveState 中搜索“惰性列表”或“惰性序列”配方,因为其中有一些方法可以执行此操作。)但这足以显示示例。
现在,这对我们有什么帮助?事实并非如此;*lst在遗嘱上,DefaultList只是尝试从事物中创建一个元组,为我们提供与已有数量完全相同的参数。但是如果你有一个版本format可以只接受一系列参数呢?然后你就可以通过你的DefaultList并且它会起作用。
你确实有:Formatter.vformat。
>>> string.Formatter().vformat('{0} {1} {2}', DefaultList([0, 1]), {})
'0 1 -'
Run Code Online (Sandbox Code Playgroud)
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], {}))
Run Code Online (Sandbox Code Playgroud)
当然,您仍然需要将迭代器包装在提供序列协议的东西中。
当我们这样做时,如果该语言具有“可迭代解包”协议,则可以更直接地解决您的问题。请参阅此处,了解提出这样的事情的 python-ideas 线程,以及该想法存在的所有问题。(另请注意,该format函数会使这变得更加棘手,因为它必须直接使用解包协议,而不是依赖解释器来神奇地完成它。但是,假设它这样做,那么您只需要编写一个非常简单的以及处理它的任何可迭代对象的通用包装器__unpack__。)