生成器可以在python中与string.format一起使用吗?

前端之家收集整理的这篇文章主要介绍了生成器可以在python中与string.format一起使用吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
"{},{},{}".format(*(1,2,3,4,5))

打印:

'1,3'

只要格式中的{}数不超过元组的长度,这就有效.我想让它适用于任意长度的元组,如果长度不足则用-s填充它.为了避免对{}的数量做出假设,我想使用一个生成器.这就是我的想法:

def tup(*args):
    for s in itertools.chain(args,itertools.repeat('-')):
        yield s

print "{},{}".format(*tup(1,2))

预期:

'1,-'

但它永远不会回归.你能用发电机吗?有更好的方法吗?

解决方法

如果你考虑一下,除了变量参数解包一次解包的事实之外,还有一个事实是格式不一定按顺序采用它的参数,如'{2} {1} {0}’.

如果格式只是采用一个序列而不是需要单独的参数,你可以通过构建一个正确的序列来解决这个问题.这是一个简单的例子:

class DefaultList(list):
    def __getitem__(self,idx):
        try:
            return super(DefaultList,self).__getitem__(idx)
        except IndexError:
            return '-'

当然,你的真实版本将包装一个任意的可迭代,而不是子类列表,并且可能必须使用tee或内部缓存并按要求提取新值,只有在你通过结束时才是默认值. (您可能希望在ActiveState中搜索“惰性列表”或“延迟序列”配方,因为其中有一些可以执行此操作.)但这足以显示示例.

现在,这对我们有什么帮助?它没有; *在一个DefaultList上只会尝试从该东西中创建一个元组,为我们提供完全相同数量的参数.但是如果你有一个版本的格式可以只采取一系列的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,kwargs):
        try:
            return super(DefaultFormatter,self).get_value(key,kwargs)
        except IndexError:
            return '-'

f = DefaultFormatter('-')

print(f.vformat('{0} {2}',[0],{}))
print(f.vformat('{0} {2}',[0,1,3],{}))

当然,你仍然需要将迭代器包装在提供Sequence协议的东西中.

在我们处理它的同时,如果语言具有“可迭代解包”协议,则可以更直接地解决您的问题.请参阅here,了解提出这样一个问题的python-ideas线程,以及该想法所带来的所有问题. (另请注意,格式化函数会使这更棘手,因为它必须直接使用解包协议而不是依赖于解释器来神奇地执行它.但是,假设它这样做,那么你只需要写一个非常简单和通用的包装器,可以处理__unpack__的任何迭代.)

原文链接:https://www.f2er.com/python/186192.html

猜你在找的Python相关文章