4

ダックタイピングの考え方は理解できたので、コードでもっと頻繁に使用したいと思います。ただし、潜在的な問題が 1 つあります。名前の衝突です。

オブジェクトに何かをさせたいとします。適切なメソッドを知っているので、それを呼び出して何が起こるかを確認するだけです。一般に、次の 3 つの結果が考えられます。

  1. メソッドが見つからず、AttributeError例外が発生します。これは、オブジェクトが私が思っているものではないことを示しています。ダックタイピングを使用すると、そのような例外をキャッチするか、外側のスコープにそれを処理させる (またはプログラムを終了させる) ことをいとわないので、それは問題ありません。

  2. メソッドが見つかり、まさに私が望んでいることを実行し、すべてが素晴らしいです。

  3. メソッドは見つかりましたが、必要なメソッドではありません。これは、まったく無関係なクラスの同じ名前のメソッドです。矛盾した状態が後で検出されるか、最悪の場合、プログラムが暗黙のうちに誤った出力を生成するまで、実行が続行されます。

これで、質の高い名前が結果 #3 の可能性をいかに減らすことができるかがわかります。しかし、プロジェクトが結合され、コードが再利用され、ライブラリが交換され、ある時点で 2 つのメソッドが同じ名前を持ち、完全に無関係である可能性が非常に高くなります (つまり、ポリモーフィズムで互いに置き換えられることを意図していません)。

私が考えていた解決策の 1 つは、メソッド名のレジストリを追加することです。各レジストリ レコードには、次のものが含まれます。

  • メソッド名 (一意、つまり、名前ごとに 1 つのレコードのみ)
  • その一般化された説明 (つまり、それが呼び出される可能性のあるすべてのインスタンスに適用可能)
  • 使用する予定のクラスのセット

メソッドが新しいクラスに追加された場合、そのクラスを (手動で) レジストリに追加する必要があります。その時点で、プログラマーはおそらくメソッドが既に付けられている意味と一致していないことに気付き、必要に応じて別の名前を使用します。

メソッドが呼び出されるたびに、プログラムは名前がレジストリにあり、インスタンスのクラスがレコード内のクラスの 1 つであることを自動的に確認します。そうでない場合は、例外が発生します。

これが非常に難しいアプローチであることは理解していますが、精度が重要な場合には、役立つ可能性があることがわかります。(Python またはその他の動的型付け言語で) 試しましたか? 似たようなことをするツールはありますか?検討する価値のある他のアプローチはありますか?

注: 名前空間の汚染を回避することが正しいアプローチであるグローバル レベルでの名前の競合については言及していません。メソッド名の衝突について言及しています。これらは名前空間の影響を受けません。

4

4 に答える 4

4

まあ、これが重要な場合は、おそらくダックタイピングを使用すべきではありません...

実際には、プログラムは有限のシステムであり、特定のルーチンに渡される可能性のある型の範囲によって、心配している問題が発生することはありません (ほとんどの場合、渡される型は 1 つだけです)。

しかし、とにかくこの問題に対処したい場合は、Python がABC (抽象基本クラス) を提供しています。これらにより、「タイプ」を任意のメソッドセットに関連付けることができるため、提案するレジストリのように機能します(通常の方法で ABC から継承するか、単に「登録」することができます)。

次に、これらのタイプを手動でチェックするか、pytypのデコレーターを使用してチェックを自動化できます。

しかし、私は pytyp の作成者であり、これらの質問を興味深いと感じていますが、個人的にはそのようなアプローチが有用だとは思いません。実際には、あなたが心配していることは単純に起こりません (何か心配したい場合は、高階関数を使用する際の型からのドキュメントの欠如に注意してください!)。

PS 注 - ABC は純粋にメタデータです。彼らは何も強制しません。また、pytyp デコレーターでのチェックは非常に非効率的です。これは、重要な場合にのみ実行する必要があります。

于 2012-04-05T18:40:37.030 に答える
0

問題に対処するには、抽象基本クラスを調べてください。これらは、この問題に対処するためのPythonの方法です。基本クラスで一般的な動作を定義でき、特定のオブジェクトが抽象基本クラスの「仮想基本クラス」であるかどうかを判断する方法を定義することもできます。これは、すべてのクラスがレジストリについて事前に知っている必要がなく、説明しているレジストリをいくらか模倣します。

ただし、実際には、この問題は予想されるほど頻繁には発生しません。メソッドが期待どおりに機能しない場合、__iter__メソッドまたはメソッドを持つオブジェクトは単純に壊れます。__str__同様に、関数の引数にその.callback()上に定義されたメソッドが必要であると言う場合、人々は正しいことをするでしょう。

于 2012-04-05T18:43:58.460 に答える
0

静的な型チェックがないためにバグが通り抜けるのではないかと心配している場合、答えは型チェックを追加することではなく、テストを作成することです。

単体テストが存在する場合、バグを検出する手段として、型チェック システムはほとんど冗長になります。型チェック システムがいくつかのバグを検出できることは事実ですが、潜在的なバグのごく一部しか検出できません。残りをキャッチするには、テストが必要です。これらの単体テストは、型チェック システムで検出できる型エラーのほとんどと、型チェック システムで検出できないバグを必ず検出します。

于 2012-04-05T19:00:36.793 に答える
0

優れたプログラミング手法に従っている場合、またはコードが Pythoic である場合は、そのような問題に直面することはめったにないでしょう。FAQを参照モジュールでインポートを使用するための「ベスト プラクティス」とは何ですか? . 通常、名前空間を乱雑にすることはお勧めしません。競合が発生するのは、Python の予約済みの名前や標準ライブラリを再利用しようとしている場合、または名前がモジュール名と競合している場合のみです。しかし、競合が発生した場合は、コードに重大な問題があります。例えば

  1. 変数に list という名前を付けたり、len という関数を定義したりするのはなぜでしょうか?
  2. 現在の名前空間にインポートしようとしているのに、なぜ誰かが変数 difflib に名前を付けるのでしょうか?
于 2012-04-05T18:40:57.093 に答える