使用Python locals()进行字符串格式化是否有缺点?

时间:2013-12-20 23:47:37

标签: python string formatting

这不是重复,因为这涉及使用较新的str.format()以上链接的问题质量较低,我认为这个问题有足够的不同以证明其正统性

问题:

有人可能会在这里遇到错误,但我们可以为str.format方法提供未使用的关键字参数。

>>> '{a}{b}'.format(a='foo', b='bar', c='baz')
'foobar'

这样可以启用以下代码:

>>> foo = 'bar'
>>> baz = 'fizzbuzz'
>>> '{foo}{baz}'.format(**locals())
'barfizzbuzz'
>>> baz = datetime.datetime.now()
>>> '{foo}_{baz}'.format(**locals())
'bar_2013-12-20 18:36:55.624000'

这是一个很好的做法,在函数闭包内做什么?

def make_foo_time_string():
    foo = 'bar'
    baz = datetime.datetime.now()
    return '{foo}{baz}'.format(**locals())

可能的缺点是什么?使用额外周期加载的额外变量?这是方便吗? 我不记得看到这个用得多,它会被认为是Python的惯用语吗?

更新我找到了使用旧样式字符串插值的规范建议用法:https://wiki.python.org/moin/PythonSpeed/PerformanceTips 然而,它似乎确实是一个相当古老的文件。

  

“更好的是,为了便于阅读(除了作为程序员之外,这与效率无关),使用字典替换:”

out = "<html>%(head)s%(prologue)s%(query)s%(tail)s</html>" % locals()

2 个答案:

答案 0 :(得分:6)

  

可能的缺点是什么?使用额外周期加载的额外变量?这是方便吗?我不记得看到这个用得多,它会被认为是Python的惯用语吗?

你只是遇到了最大的缺点:它不是惯用的。

原因它不是惯用的,正如Zen所说,&#34;明确比隐含更好。&#34;

显然很多人都不会写'{foo}{baz}'.format(foo=foo, baz=baz)(特别是如果你超过2个变量),因为这非常可怕地违反DRY ...但是有一种方法可以做到这一点,就像简明扼要地作为您的代码,至少是明确的,并且不需要像locals这样的高级知识类型:

>>> '{}{}'.format(foo, baz)

当格​​式字符串是动态的时,这不起作用,但这是一个好的事物,因为动态格式字符串通常是一个红旗。

(有些人也认为&#34;静态检查&#34;在这里受益 - 如果你将名字嵌入到格式字符串中,那么你使用简单NameError的错误要少得多format的参数中不存在的变量。我把它放在靠近底部的括号中,因为我个人认为这个论点非常好,即使我已多次看到它...)

然而,正如任何样式/成语问题一样,对此问题没有普遍的一致意见,并且经常在python-list(和python-ideas,当有人建议制作locals()的方法时进行辩论。默认为format或类似内容),直到每个人都停止关注。

答案 1 :(得分:5)

来自PEP 20 - Python的禅宗:

  

明确比隐含更好。

在这里,那可能(对我而言, )意味着最好拼出你想做的事情。假设您最终希望用方法调用替换它并从

开始
>>> '{a}{b}'.format(a='foo', b='bar', c='baz')

>>> mymethod(a='foo', b='bar', c='baz')

Voila--完成了。但更实际的是,PyLint和朋友可以为您提供有关显式版本的有价值信息。假设你有:

foo = '123'
print '{foo}'.format(**locals())

大。这样可行。但是如果你忘了分配给foo怎么办?你的代码会爆炸,你不知道为什么。与:比较:

print '{foo}'.format(foo=foo)

PyLint会给你一个“Undefined name:'foo'”错误。好极了!在您开始寻找它之前发现的错误。

一般来说,要明确。它是Pythonic,但它也是非常好的做法。