以下是一些代码:
foo = "Bears"
"Lions, Tigers and %(foo)s" % locals()
我的PEP8 linter(SublimeLinter)抱怨这个,因为foo是“未引用的”。我的问题是PEP8是否应该将这种类型的字符串插值计为“引用”,或者是否有充分的理由考虑这种“坏的风格”。
答案 0 :(得分:5)
好吧,未被引用。可疑风格的部分是使用locals()
来访问变量而不是仅通过名称访问变量。请参阅this previous question了解为什么这是一个可疑的想法。这不是一件可怕的事情,但对于你想长期保持的节目来说,这不是一个好的风格。
编辑:当你使用文字格式字符串时,它似乎更明确。但上一篇文章的部分内容是,在较大的程序中,您可能会使用文字格式字符串结束而不是。如果它是一个小程序,你不在乎,继续使用它。但是警告可能导致可维护性问题的事情也是风格指南和短信的一部分。
此外,locals
不是在文字中明确引用的名称的规范表示。它是本地命名空间中所有名称的规范表示。如果你愿意的话,你仍然可以这样做,但它基本上是一个宽松/草率的替代方案,明确地使用你正在使用的名字,这也就是那些短信应该警告你的东西。
答案 1 :(得分:1)
即使您拒绝BrenBarn的参数,即foo
未被引用,如果您接受了应该标记在字符串格式中传递locals()
的参数,那么可能不值得写入代码来考虑{ {1}}引用。
首先,在额外代码有用的每种情况下,无论如何都不能接受构造,并且用户将不得不忽略lint警告。是的,当实际上只有一个问题时,给用户两个 lint警告忽略是有害的,特别是如果其中一个警告有些误导。但是,编写非常复杂的代码并在漏洞中引入新的错误是不是有害?
你还必须考虑到实际工作,linter不仅要识别foo
格式,还要识别%
格式,以及其他所有字符串格式,HTML模板等用户可能正在使用。在实践中,这意味着处理各种非常常见的形式,并为用户提供某种钩子以描述其他任何形式。
而且,最重要的是,即使你认为它不应该与任意生成的格式字符串一起使用,它肯定必须至少使用l10n。这怎么样?如果格式字符串是由gettext之类的东西生成的,则linter无法知道是否引用{}
,除非它可以检查所有翻译并看到其中至少有一个引用foo
- 这意味着它必须理解(或有钩子教导)每个字符串翻译机制,并且可以访问翻译数据库。
所以,我建议,即使你认为在这种情况下警告是虚假的,你仍然把它留在那里。最多添加符合警告条件的内容:
的函数中
foo
可能未引用,但在使用foo
答案 2 :(得分:0)
以下内容也不会使SublimeLinter感到高兴,它查找字符串中引用的每个变量名称,并替换命名空间映射中的相应值,默认为调用者的locals
。因此,它显示了SublimeLinter在尝试确定Python中是否引用了某些内容时所具有的固有限制。我的建议是忽略SublimeLinter或添加代码来伪造它,比如foo = foo
。我不得不做类似后者的事情来摆脱C编译器关于合法和有意的事情的警告。
import re
import sys
SUB_RE = re.compile(r"%\((.*?)\)s")
def local_vars_subst(s, namespace=None):
if namespace is None:
namespace = sys._getframe(1).f_locals
def repl(matchobj):
var = matchobj.group(1).strip()
try:
retval = namespace[var]
except KeyError:
retval = "<undefined>"
return retval
return SUB_RE.sub(repl, s)
foo = "Bears"
print local_vars_subst("Lions, Tigers and %(foo)s")