「厳密に使用する」Python コンパイラは必要ですか?
-
03-07-2019 - |
質問
が存在します Python用の静的解析ツール, ただし、コンパイル時のチェックは正反対の傾向があります。 実行時バインディングの哲学 Python はそれを受け入れます。その 可能 標準の Python インタープリターを静的分析ツールでラップして、いくつかの "厳密に使用する"のような制約がありますが、そのようなものが広く採用されている様子はありません。
Python に関して、「厳密な使用」動作を不必要にする、または特に望ましくないものはありますか?
あるいは、「厳密な使用」動作は、広く採用されているにもかかわらず、Perl では不要なのでしょうか?
注記:「必要」とは「実質的に必要」という意味であり、厳密に必要というわけではありません。明らかにあなたです できる Perl は "use strict" なしで記述しますが、(私が見た限りでは) ほとんどの Perl プログラマは する これを使って。
注記:Python インタープリター ラッパーは必要ありません。 必要とする 「use strict」のような制約 -- 通常のインタプリタでは無視される「use strict」に似た疑似プラグマを使用できます。私は言語レベルの機能を追加することについて話しているのではありません。
アップデート:Perl での "use strict" の機能をコメントごとに説明します。(公式ドキュメントへのリンクは最初の段落にあります。)
「use strict」ディレクティブには 3 つの異なるコンポーネントがありますが、そのうち本当に興味深いのは 2 つだけです。
厳密な変数を使用します。プログラム内での字句スコープの変数の使用を静的にチェックします。(Python では、基本的には
global
範囲とlocal
範囲)。多くの Python リンターはこの種のことをチェックします。これが彼らが実行できる唯一の静的分析であるため、リンターはあなたが単純な字句スコープを使用していると想定し、あなたが黙るよう指示するまで、その意味で間違っていると思われるものについて警告します。つまりFOO = 12 foo += 3
名前空間で何も特別なことをしていない場合、これはタイプミスをチェックするのに役立ちます。
厳密な参照を使用します。シンボリックな名前空間の逆参照を防止します。Python に最も近いものは、
locals()
そしてglobals()
シンボリック バインディングと識別子の検索を実行します。厳密なサブを使用します。Python には実際の類似物はありません。
解決
" Pythonが採用する実行時バインディングの哲学...不要な動作[特に]望ましくない動作」
かなり良い要約。ありがとう。
それは本質的にそれです。静的解析ツールは、Pythonを役立たせるのに十分ではありません。
編集
"私たちはそれを必要としないなぜと、それに関連して、Perlプログラマーが必要だと思う理由について内省するように求めています。"
その理由は、まさにあなたがすでに与えた理由です。役に立たないので必要ありません。明らかに、あなたはその答えが好きではありませんが、それ以上言うことはありません。コンパイル時またはプリコンパイル時のチェックはまったく役に立ちません。
ただし、時間をかけて再度質問をしたため、あなたがすでに行った回答の証拠を追加します。
Javaを書くのは、Pythonを書くのとほぼ同じです。 Javaの静的型チェックは、ロジックの問題を防止しません。パフォーマンス要件を満たすのを促進しません。ユースケースを満たすのに役立ちません。単体テストの量さえ削減しません。
静的な型チェックはメソッドの偶発的な誤用を発見しますが、Pythonでも同じように素早く発見できます。 Pythonでは、実行されないため、ユニットテスト時に見つけます。注:多くの巧妙な単体テストで間違った型が見つかると言っているのではなく、アサーションをテストするのに十分なほど実行されない未処理の例外によって、ほとんどの間違った型の問題が見つかっていると言っています。
Pythonistaが静的チェックに時間を無駄にしない理由は簡単です。必要ありません。価値はありません。これは、経済的なメリットのない分析レベルです。実在の人々が実データで抱えている実在の問題を解決することはできません。
言語(問題のドメインやライブラリではない)に関連する最も一般的なSO Pythonの質問をご覧ください。
"には違いがありますか? fooはNoneです" " foo == None&quot ;? - ==
vs. is
これに役立つ静的チェックはありません。また、「==」と「 Pythonの場合は?
**(二重星印)および*(星印)の機能パラメータ?- * x
はリストを提供し、 ** x
は辞書を提供します。これがわからない場合、これらのタイプに対して不適切な操作を行おうとすると、プログラムはすぐに停止します。 "プログラムが「不適切な」ことを何もしない場合はどうなりますか?」その後、プログラムが動作します。 「ナフは言った。
「Enum」をPython?-これは、ある種の制限されたドメインタイプの嘆願です。クラスレベルの値を持つクラスは、ほとんどその仕事をします。 "誰かが割り当てを変更した場合"。簡単に構築できます。 __ set __
をオーバーライドして、例外を発生させます。はい、静的チェックでこれを見つけることができます。いいえ、実際には誰かが列挙定数と変数について混乱することはありません。そして、それらを実行すると、実行時に簡単に見つけることができます。 「ロジックが実行されない場合」まあ、それは貧弱なデザインと貧弱な単体テストです。コンパイラエラーをスローし、テストされていない間違ったロジックを入力することは、テストされていない動的言語で起こることと同じです。
ジェネレーター式とリスト内包表記-静的チェックは解決に役立ちませんこの質問。
他のヒント
まあ、私はPythonプログラマーではありませんが、答えは「はい」と言います。
任意の名前の変数をいつでも作成できる動的言語では、 'strict'プラグマを使用できます。
Strict vars(Perlのstrictのオプションの1つ、 'use strict'は一度にすべてをオンにします)Perlでは、使用する前にすべての変数を宣言する必要があります。つまり、次のコード:
my $strict_is_good = 'foo';
$strict_iS_good .= 'COMPILE TIME FATAL ERROR';
コンパイル時に致命的なエラーを生成します。
Pythonにコンパイル時にこのコードを拒否させる方法はわかりません:
strict_is_good = 'foo';
strict_iS_good += 'RUN TIME FATAL ERROR';
strict_iS_good
が未定義であるという実行時例外が発生します。ただし、コードが実行される場合のみ。テストスイートのカバレッジが100%でない場合、このバグを簡単に出荷できます。
この動作を持たない言語(PHPなど)で仕事をしていると、いつも緊張します。私は完璧なタイピストではありません。単純だが見つけにくいタイプミスは、コードを追跡するのが難しい方法でコードを失敗させる可能性があります。
したがって、繰り返しになりますが、 YES Pythonは、 'strict'プラグマを使用して、コンパイル時にチェックできる項目のコンパイル時チェックをオンにします。追加する他のチェックは考えられませんが、より優れたPythonプログラマーはおそらく考えられるでしょう。
注私は、Perlでのstict varsの実用的な効果に焦点を当て、詳細のいくつかを詳しく説明しています。すべての詳細を本当に知りたい場合は、 strictのperldoc を参照してください。
更新:コメントへの返信
Jason Baker :パイリントのような静的チェッカーは便利です。しかし、それらは余分なステップであり、多くの場合スキップされます。コンパイラにいくつかの基本的なチェックを組み込むと、これらのチェックが一貫して実行されることが保証されます。これらのチェックがプラグマによって制御可能である場合、チェックのコストに関連する異議さえ無意味になります。
popcnt :pythonが実行時例外を生成することを知っています。私もそう言った。可能な場合は、コンパイル時のチェックを推奨します。投稿を読み直してください。
mpeters :すべてのエラーをコードのコンピューター分析で見つけることはできません。これは停止する問題の解決に相当します。さらに悪いことに、割り当てのタイプミスを見つけるには、コンパイラがあなたの意図を知り、あなたの意図がコードと異なる場所を見つける必要があります。これは明らかに不可能です。
ただし、これはチェックを行わないという意味ではありません。検出しやすい問題のクラスがある場合は、それらをトラップするのが理にかなっています。
pylintとpycheckerに精通していないので、キャッチするエラーのクラスを言うことができません。私が言ったように、私はPythonに非常に不慣れです。
これらの静的解析プログラムは便利です。ただし、コンパイラの機能を複製しない限り、コンパイラは常に「知っている」立場にあると信じています。どの静的チェッカーよりもプログラムについての詳細。可能な限りエラーを減らすためにこれを利用しないのはもったいないようです。
更新2:
cdleary-理論上、私はあなたに同意します、静的アナライザーはコンパイラーができることを検証できます。 Pythonの場合は、これで十分です。
ただし、コンパイラが十分に複雑な場合(特にコンパイルの方法を変更するプラグマが多数ある場合、またはPerlのようにコンパイル時にコードを実行できる場合)、静的アナライザーはコンパイラの複雑さに近づく必要があります分析を行う/ interpreter。
はい、複雑なコンパイラとコンパイル時のコードの実行に関するすべての話は、私のPerlの背景を示しています。
私の理解では、Pythonにはプラグマがなく、コンパイル時に任意のコードを実行できません。したがって、私が間違っているか、これらの機能が追加されない限り、静的アナライザーの比較的単純なパーサーで十分です。間違いなくヘル
Pythonには、スクリプトの構文を変更できるものがあります。
from __future__ import print_function
およびその他の構文の意味を持つ将来の機能。 Pythonの構文は、歴史的なPerlよりも厳密で安定しており、より明確に定義されているだけです。 ‘厳格な参照’および‘ strict subs’ Pythonには禁止が存在していません。
‘ strict vars’タイプミスされた参照や見落とした‘ my’ sが偶発的なグローバル(まあ、Perl用語ではパッケージ変数)を作成するのを防ぐことを主な目的としています。 Pythonでこれを行うことはできません。裸の割り当てはデフォルトでローカル宣言になり、割り当てられていない裸のシンボルは例外になります。
(ユーザーが‘ global’ステートメントで宣言せずにグローバルに誤ってライトスルーしようとすると、偶発的なローカルエラー、またはより頻繁にUnboundLocalErrorが発生する場合があります。かなり迅速に習得する必要がありますが、ローカルを宣言する必要がある場合は議論の余地のあるケースです。経験豊富なPythonプログラマーのほとんどは読みやすさの負担を受け入れませんでした。)
構文に関係しない他の言語およびライブラリの変更は、 warnings システムを通じて処理されます。 。
" use strict"としていくつかの混乱があると思います。私が見ているコメントから。 (Javaのように)コンパイル時の型チェックをオンにしません。その意味で、PerlのプログラマーはPythonプログラマーと一致しています。上記のS.Lottによると、これらのタイプのチェックは論理的なバグから保護されないため、作成する必要のある単体テストの数を減らさないでください。ボンデージプログラミングの大ファンでもありません。
「厳格に使用」のリストは次のとおりです。行う:
-
シンボリック参照の使用は実行時エラーです。これにより、狂ったことを防ぐことができます(ただし、次のような便利なこともあります)
$ var = 'foo';
$ foo = 'bar';
print $$ var; #strict
で実行しない限り、これには$ fooの内容が含まれます
-
未宣言の変数を使用すると実行時エラーが発生します(つまり、使用する前に変数のスコープを宣言するために" my"、" our"または" local"を使用する必要があります。
-
すべてのベアワードは、コンパイル時の構文エラーと見なされます。ベアワードは、シンボルまたはサブルーチンとして宣言されていない単語です。これは主に、過去に行われたものの違法であると考えられるものを違法にすることです。
Pythonには真のレキシカルスコープがないため、厳密なvarはあまり賢明ではありません。シンボリック参照はないので、厳密な参照は必要ありません。ベアワードがないため、厳密な変数は必要ありません。
正直なところ、私が見逃しているのは語彙の範囲だけです。他の2つはPerlのいぼを考慮します。
この元の答えは正しいですが、おそらく実際的な意味で状況を説明していません。
Python 用の静的分析ツールは存在しますが、コンパイル時のチェックは、Python が採用する実行時のバインディングの哲学とは正反対である傾向があります。
PERLで「Strict」が提供するのは、コンパイル時に(通常)誤ったスペルまたは可変名がキャッチされるようにすることができることです。これにより、コードの信頼性が向上し、開発が高速化されます。しかし、そのようなことを価値のあるものにするためには、変数を宣言する必要があります。そして、Python スタイルはそれを妨げるようです。
したがって、Pythonでは、実行時に自分が作成した課題が作成されていないこと、または表現が予期しない価値に解決しているように見えることに気付くまで、誤った変数について知ることはありません。このようなエラーをキャッチするには、特にプログラムが大きくなるにつれて、人々が他の人によって開発されたコードを維持することを余儀なくされるため、時間がかかる場合があります。
Java と C/C++ はさらに一歩進んで、型チェックを行います。動機は哲学的ではなく、実用的です。できるだけ多くのエラーをできるだけ早く検出し、コードを運用環境にリリースする前にすべてのエラーを確実に除去するにはどうすればよいでしょうか?各言語は、特定の戦略を取り、重要だと思うものに基づいて、それを実行しているようです。ランタイムバインディングがサポートされていないPerlのような言語では、開発を容易にするために「厳格」を利用することは理にかなっています。
あなたが示唆したように、Perlの 'use strict'
はプラグマのようなものだと考えています。コンパイラの動作を変更します。
Perl言語の哲学は、Pythonの哲学とは異なります。のように、Perlで繰り返しハングアップするのに十分なロープが与えられます。
ラリーウォールは言語学が大好きなので、PerlからTIMTOWTDI(たとえば tim-toe-dee
)原則とPythonのZenと呼ばれるものがあります:
1つある必要があります。できれば 1つだけ-明白な方法です。
非常に簡単にpylintとPyCheckerを使用して、Pythonの use strict
の独自のフレーバー(または perl -cw * scriptname *
に類似したもの)を思いつくことができますが、言語設計にはさまざまな哲学があるため、実際にはこれに広く遭遇することはありません。
最初の投稿者へのコメントに基づいて、Pythonの import this
に精通しています。 Pythonに use strict
に相当するものが表示されない理由を明らかにするものがたくさんあります。 Python of Zenにある koan について瞑想すると、自分自身の啓発を見つけることができます。 :)
私は、宣言されていない変数への参照を検出することだけを本当に気にしていることがわかりました。 EclipseはPyDevを介したpylint統合を備えており、pylintは完全にはほど遠いものの、それで妥当な仕事をします。
これは、Pythonの動的な性質に反するものであり、コードについて何か巧妙になると、#IGNOREを時々追加する必要があります。しかし、私はそれが満足できるほどまれにしか起こらないと思います。
しかし、コマンドラインフラグの形式で利用できるようになるいくつかのパイリントのような機能のユーティリティを見ることができました。 Python 2.6の-3スイッチのようなもので、Python 2.xと3.xのコード間の非互換性のポイントを識別します。
Perlで 'use strict'なしで大きなプログラムを書くことは非常に困難です。 'use strict'を使用しない場合、変数を再度使用し、文字を省略してスペルを間違えても、プログラムは引き続き実行されます。また、結果を確認するテストケースがなければ、このようなエラーを見つけることはできません。この理由により間違った結果が得られる理由を見つけるのは非常に時間がかかります。
Perlプログラムの一部は、5,000行から10,000行のコードで構成され、数十のモジュールに分割されています。 「厳密に使用」せずに本番プログラミングを実際に行うことはできません。 "変数宣言"を強制しない言語を使用して、工場に製品コードをインストールすることは許可しません。
これが、Perl 5.12.xがデフォルトの動作として「use strict」を持つようになった理由です。それらをオフにすることができます。
PHPは、変数宣言の強制がないため、かなりの数の問題を与えてくれました。したがって、この言語を使用する小さなプログラムに限定する必要があります。
ご意見をお聞かせください...
abcParsing
Perlは彼らが言ったように無制限の言語です:)。そのため、アナウンスされる前に変数を使用できます。例:変数名" is_array"を使用する場合「&is; arrby"」と入力します、コンパイラは" use strict"なしでエラーを報告しません。 。したがって、perlで長いプログラムをコーディングするときは、「use strict」を使用することをお勧めします。ステートメント。もちろん、1回のスクリプトを実行するのに50行未満なので、必要ありません:)
「Pythonic」の理想のようです。コードは、 use strict
と同じ目的の多くを果たします。
Perlのバックグラウンドはありませんが、私が知っていることから、コードを「より信頼性の高い」ものにするために無効にする必要があるpythonの機能はありません。その意味で、不要だと言う