2

ここにいくつかのコードがあります:

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

foo が「参照されていない」ため、私の PEP8 リンター (SublimeLinter) はこれについて不平を言います。私の質問は、PEP8 がこのタイプの文字列補間を「参照」としてカウントする必要があるかどうか、またはこの「悪いスタイル」を考慮する十分な理由があるかどうかです。

4

3 に答える 3

5

うーん、参考にならない。問題のあるスタイルの部分は、locals()変数に名前でアクセスするのではなく、変数にアクセスするために使用しています。それが疑わしい考えである理由については、この前の質問を参照してください。ひどいことではありませんが、長期的に維持したいプログラムには向いていません。

編集:リテラル形式の文字列を使用すると、より明示的に見えるのは事実です。しかし、前回の投稿で要点の 1 つは、大規模なプログラムでは、リテラルの書式指定文字列を使用しないことになる可能性が高いということです。それが小さなプログラムであり、気にしない場合は、先に進んで使用してください。しかし、後で保守性の問題を引き起こす可能性があることについて警告することも、スタイルガイドとリンターの目的の一部です。

また、localsリテラルで明示的に参照されている名前の正規表現ではありません。これは、ローカル名前空間内のすべての名前の正規表現です。必要に応じてそれを行うこともできますが、基本的には、使用している名前を明示的に使用するための緩い/ずさんな代替手段です。

于 2012-12-11T19:29:13.420 に答える
1

参照されていないBrenBarnの引数を拒否した場合でも、文字列フォーマットfooの受け渡しlocals()にフラグを立てる必要があるという引数を受け入れた場合、参照されていると見なすためにコードに書き込む価値がない可能性がありfooます。

まず、その余分なコードが役立つすべての場合、構造はとにかく受け入れられず、ユーザーはとにかくlint警告を無視する必要があります。はい、特に警告の1つがやや誤解を招く場合は特に、実際に問題が1つしかない場合に、ユーザーに2つのlint警告を無視することには害があります。しかし、非常に複雑なコードを書くことを正当化し、リンターに新しいバグを導入することは十分に害がありますか?

また、これが実際に機能するためには、リンターは%フォーマットだけでなく、{}フォーマット、およびユーザーが使用できる他のすべての種類の文字列フォーマット、HTMLテンプレートなども認識しなければならないことも考慮する必要があります。実際には、これはさまざまな非常に一般的なフォームを処理し、ユーザーが他のことを説明するためのある種のフックを提供することを意味します。

さらに、任意に生成されたフォーマット文字列で機能するとは思わない場合でも、少なくともl10nで機能する必要があります。それはどのように機能しますか?フォーマット文字列がgettextのようなものによって生成された場合、リンターは、fooすべての翻訳をチェックして、それらの少なくとも1つが参照していることを確認できない限り、参照されているかどうかを知る方法がありません。つまりfoo、理解する必要があります(またはフックが必要です)。教えられる)すべての文字列翻訳メカニズム、および翻訳データベースへのアクセス権を持っています。

したがって、この場合の警告を偽物と見なしても、とにかくそのままにしておくことをお勧めします。せいぜい、警告を修飾するものを追加してください。

foo参照されていない可能性がありますが、locals()

于 2012-12-11T20:13:12.123 に答える
0

以下も SublimeLinter を満足させるものではありません。文字列で参照されている各変数名を検索し、名前空間マッピングから対応する値を置き換えます。デフォルトは呼び出し元のlocalsです。そのため、Python で何かが参照されているかどうかを判断しようとするときに、SublimeLinter のようなユーティリティに固有の制限があることを示しています)。私のアドバイスは、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 に答える