2

这是一些代码:

foo = "Bears"
"Lions, Tigers and %(foo)s" % locals()

我的 PEP8 linter (SublimeLinter) 抱怨这一点,因为 foo 是“未引用的”。我的问题是 PEP8 是否应该将这种类型的字符串插值计为“引用”,或者是否有充分的理由考虑这种“不良风格”。

4

3 回答 3

5

好吧,它没有被引用。风格有问题的部分是locals()用来访问变量,而不是仅仅通过名称访问它们。请参阅上一个问题,了解为什么这是一个可疑的想法。这不是一件可怕的事情,但对于您想要长期维护的程序来说,这不是一种好的风格。

编辑:确实,当您使用文字格式字符串时,它似乎更明确。但是上一篇文章的部分观点是,在一个更大的程序中,您可能最终不会使用文字格式字符串。如果它是一个小程序并且您不在乎,请继续使用它。但是,对以后可能导致可维护性问题的事情发出警告也是样式指南和 linter 的一部分。

此外,locals这不是在文字中明确引用的名称的规范表示。它是本地命名空间中所有名称的规范表示。如果你愿意,你仍然可以这样做,但它基本上是一个松散/草率的替代方案,而不是显式使用你正在使用的名称,这又是 linter 应该警告你的那种事情。

于 2012-12-11T19:29:13.420 回答
1

即使您拒绝 BrenBarn 的foo未引用参数,如果您接受locals()应该标记传入字符串格式的参数,则可能不值得将代码写入考虑foo引用。

首先,在任何额外代码会有所帮助的情况下,该构造无论如何都是不可接受的,并且无论如何用户都将不得不忽略 lint 警告。是的,当实际上只有一个问题时,给用户两个lint 警告以忽略是有一些危害的,特别是如果其中一个警告有点误导。但是,证明编写非常复杂的代码并在 linter 中引入新错误是否足够有害?

您还必须考虑到,要使其真正起作用,linter 不仅要识别%格式,还要识别{}格式,以及用户可能使用的所有其他类型的字符串格式、HTML 模板等。在实践中,这意味着处理各种非常常见的形式,并为用户提供某种钩子来描述其他任何内容。

而且,最重要的是,即使您认为它不应该与任意生成的格式字符串一起使用,它肯定至少必须与 l10n 一起使用。这将如何运作?如果格式字符串是由 gettext 之类的东西生成的,则 linter 无法知道是否foo被引用,除非它可以检查所有翻译并看到其中至少一个引用foo- 这意味着它必须理解(或有钩子被教导)每个字符串翻译机制,并可以访问翻译数据库。

所以,我建议,即使你认为这种情况下的警告是虚假的,你还是把它留在那里。最多添加一些符合警告的内容:

foo可能未引用,但在使用的函数中locals()

于 2012-12-11T20:13:12.123 回答
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")
于 2012-12-11T20:56:47.110 回答