生成器可以在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,它会工作. 而你确实拥有: >>> 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__的任何迭代.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |