4

古いコードをさまざまな目的のために何度も何度も変更し、適応させなければならないことに気づきますが、2 つ前のバージョンと同じ目的を実装するために、2 つのバージョンが必要になることもあります。

この一例は、素数を扱う関数です。時々、私が必要とするのは n 個の素数のリストです。時々私が必要とするのはn番目の素数です。たぶん、機能から3番目のニーズに出くわすでしょう。

同じプロセスを実行する必要がありますが、異なる値を返すだけです。同じコードを常に変更するよりも、これを行うためのより良い方法があるに違いないと思いました。私が思いついた可能な代替案は次のとおりです。

  1. タプルまたはリストを返しますが、何千ものアイテムのリストを含むすべての種類のデータ型が存在するため、これはちょっと面倒です。

  2. 入力ステートメントを使用してコードを指示しますが、[実行] をクリックするとすべてが実行されるようにしたいと思います。

  3. クラスの機能を利用してクラスのプロパティを返し、必要な場所にアクセスする方法を理解してください。これは私にとって最もクリーンな解決策のようですが、私はまだこれに慣れていないのでわかりません。

  4. 再利用可能な関数ごとに 5 つのバージョンを作成するだけです。

私は悪いプログラマーになりたくないので、どの選択が正しい選択ですか? あるいは、思いもよらなかったことができるかもしれません。

4

3 に答える 3

6

モジュール式の再利用可能なコード

あなたの質問は確かに重要です。プログラマーの日常生活において重要です。それは質問です:

私のコードは再利用可能ですか?

そうでない場合、コードの冗長性が発生し、同じコード行が複数の場所に存在します。これは、バグの最良の出発点です。たとえば、潜在的な問題を発見したなどの理由で、何らかの方法で動作を変更したいとします。次に、1 か所で変更しますが、2 番目の場所は忘れてしまいます。特に、コードが 1,000、10,000、または 100,000 行のコードに達する場合。

これは、 SRPSingle-Responsibilty-Principleに要約されています。すべてのクラス (関数にも適用可能) は、「ただ 1 つのことを行う必要がある」という 1 つの決定のみを持つべきであると述べています。関数が複数のことを行う場合は、小さなチャンク、小さなタスクに分割する必要があります。

10 行または 20 行を超える (実際の) コードを含む関数に出くわす (または作成する) たびに、懐疑的になる必要があります。そのような機能がこの原則に固執することはめったにありません。

あなたの例では、個々のタスクとして識別できます。

  1. 素数を 1 つずつ生成します (生成とは、使用することを意味しyieldます)
  2. n素数を集める。1. を使用し、それらをリストに入れます
  3. n素数を取得します。1. を使用しますが、すべての番号を保存するのではなく、th を待つだけnです。2.ほど多くのメモリを消費しません。
  4. 素数のペアを見つける: 1 を使用し、前の数を記憶し、現在の数との差が 2 の場合、このペアを生成します
  5. 素数のすべてのペアを収集する: 4. を使用してそれらをリストに入れます
  6. ...
  7. ...

リストは拡張可能で、どのレベルでも再利用できます。すべての関数のコードが 10 行を超えることはなく、毎回車輪を再発明する必要はありません。

それらをすべてモジュールに入れて、素数に関連するオイラー問題のすべてのスクリプトから使用します。

一般に、オイラー問題スクリプト用の小さなライブラリを開始しました。"Project Euler" で再利用可能なコードを書くことに慣れることができます。

キーワード引数

あなたが言及しなかった別のオプション (私が理解している限り) は、オプションのキーワード引数の使用です。小さくてアトミックな関数が複雑すぎると思う場合 (慣れる必要があると私は強く主張しますが)、戻り値を制御するキーワード引数を追加できます。たとえば、一部のscipy関数にはfull_output、bool を取るパラメータ があります。False (デフォルト) の場合は、最も重要な情報 (最適化された値など) のみが返されます。True の場合は、最適化のパフォーマンスや収束にかかった反復回数などの補足情報も返されます。

パラメータを、可能な値などで定義できoutput_modeます。"list""last"

おすすめ

小さくて再利用可能なコードのチャンクに固執します。これに慣れることは、「Project Euler」で得られる最も価値のあることの 1 つです。

述べる

私が提案する再利用可能な関数のパターンを実装しようとすると、ポイント 1: How to create a generator-style function for this? ですぐに問題に遭遇する可能性があります。たとえば、ふるい法を使用する場合。しかし、それはそれほど悪くはありません。

于 2013-02-08T07:21:59.693 に答える
0

関数をできる限り削減し、再利用してください。

たとえば、next_primeと によって繰り返し呼び出される関数があるn_primesとしn_th_primeます。

これにより、素数を数えるより効率的な方法を思いついた場合でも、コードをより保守しやすくなりますnext_prime

さらに、アウトプットはできるだけニュートラルにする必要があります。関数が複数の値を返す場合、カンマ区切りの文字列ではなくlist、またはジェネレーターを返す必要があります。

于 2013-02-08T07:19:33.227 に答える
0

私の推測では、以下を含むモジュールを作成します。

  1. プライベート コア関数 (例: n 番目の最初の素数のリストを返す、またはより一般的なもの)
  2. コア関数を使用し、さまざまな方法で出力を準備するいくつかのラッパー/ユーティリティ関数。(例:n番目の素数)
于 2013-02-08T06:46:40.467 に答える