ここではPythonについて話していますが、これはおそらくほとんどの言語に当てはまると思います。私が可変オブジェクトを持っている場合、インプレース操作でもオブジェクトを返すのは悪い考えですか?ほとんどの例のように、オブジェクトを修正してNone
を返すようです。たとえば、list.sort
です。インプレース操作でオブジェクトを返すのは悪い考えですか?
答えて
はい、悪い考えです。その理由は、インプレース操作と非インプレース操作が明らかに同じ出力を持つ場合、プログラマは、インプレース操作と非インプレース操作(List.sort()
対sorted()
)を頻繁に混在させ、エラーを検出する。
自分自身を返すインプレース操作では、メソッドチェーニングを実行できますが、偶然にチェーンの途中に副作用のある関数を埋め込む可能性があるため、これは悪い方法です。
このようなエラーを防ぐには、メソッドチェーンには副作用を持つメソッドが1つしかなく、その関数はチェーンの最後にある必要があります。チェーン内のそれ以前の関数は、副作用なしに入力を変換する必要があります(例えば、ツリーのナビゲート、文字列のスライスなど)。インプレース操作が自分自身に戻ると、プログラマーはコピーを返す代替関数の代わりに誤って使用することになり、副作用(List.sort()
対sorted()
)がなくなり、エラーが発生しやすくなりますデバッグ。
これは、Pythonの標準ライブラリ関数が常にコピーを返すかNone
を返して、オブジェクトをインプレースで修正しますが、インプレースでオブジェクトを変更したり、自分自身を戻したりすることがないためです。 Djangoのような他のPythonライブラリもこの方法に従います(Djangoについてはthis very similar questionを参照してください)。
原則として合意しましたが、私は例外があると思います。 Eg1:メソッドのセマンティックが、jQueryの '.empty()'のように、適切な操作である場合。 Eg2:APIが非常に一般的に使用されているため、初心者から始めて知り、jQueryの '.append() 'のようなコピーを返すバージョンはありません –
メソッド名が現在の時制動詞なので、操作がインプレースで動作することを人々が明らかにすることを意味します。私はいつも 'list.sort'がインプレースで動いていたことを思い出す前に、Pythonを学んだ後、長い時間がかかりました。 – asmeurer
インプレース操作でチェーンを終了することとまだ混乱していませんか? 'a.sort()'と 'a [:2] .sort()'は全く違うことをしようとしています(ビューを使うnumpy 'array'のようなものを使うと違うでしょう)。たぶんポイントは、 'sort'が' None'を返すことは、 'a [:2] .sort()'が役に立つと思うことからあなたを守りますか? – asmeurer
ユースケースによって異なると思われます。私は、結果を使用しない以外に、インプレース操作からオブジェクトを戻すのが痛いのはなぜか分かりませんが、あなたが純粋な機能主義について非常に慎重でない場合は、実際には問題にはなりません。 jQueryのような呼び出し連鎖パターンが好きなので、関数を使用したときに関数がそれを返したときにはそれを感謝します。
変更されたオブジェクトを修正したメソッドから戻すと、いくつかの利点がありますが、Pythonではお勧めできません。変更操作後にself
を返すと、オブジェクト上でmethod chainingを実行することができます。これは、同じオブジェクトに対して複数のメソッドを実行する便利な方法です。オブジェクト指向プログラミングでは非常に一般的なイディオムです。そして、メソッド連鎖は、fluent interfacesの直接的な実装を可能にします。また、いくつかの関数プログラミングイディオムをより簡単に表現することができます。
例を挙げておきます:Pythonでは、Mokaライブラリはメソッドチェインを使用しています。 Javaでは、StringBuilder
クラスは同じオブジェクト上に複数のappend()
呼び出しを許可します。 JavaScriptでは、JQueryはメソッド連鎖を広範囲に使用します。 Smalltalkは、このアイデアを次のレベルに引き継いでいます。デフォルトでは、すべてメソッドは、特に指定がない限りself
を返します。したがって、メソッド連鎖を推奨します。これはデフォルトでNone
を返すPythonと対照的です。
PythonはCommand/Query Separation Principleに準拠しているため、このイディオムの使用は一般的ではありません。「すべてのメソッドは、アクションを実行するコマンドまたは呼び出し元にデータを返すクエリのいずれかでなければなりません。どちらも"。
最終的にself
を返すことが良いか悪いかに関わらず、すべてのことを考慮して、個人的な味と混合されたプログラミング文化と慣習の問題です。上で述べたように、いくつかのプログラミング言語はこれを(Smalltalkのように)推奨しますが、他のプログラミング言語はPythonのようにそれを妨げます。それぞれの視点には長所と短所があり、熱い議論につながります。もしもあなたが本書のPythonistであれば、self
を返すのをやめてください。このルールを破ることは時には便利なことがあることに注意してください。
優れた答え、特にコマンド/クエリ分離原則へのリンクをありがとう私は最近迷っているデザインのトレードオフにラベルをつけています。 – FMc
- 1. カスタムプレリュードモジュール - 悪い考えですか?
- 2. PyCuda DeviceAllocationオブジェクトを交換するのは悪い考えですか?
- 3. ラップトップにデータベースでCRUD操作を直接実行させるのは悪い考えですか?
- 4. Linqはselect()です。SingleorDefault()は悪い考えですか?
- 5. 水平スクロールバーを隠すのは悪い考えですか?
- 6. ネイティブメソッドをオーバーライドするのはなぜ悪い考えですか?
- 7. GCCの-fms-extensionsを使うのは悪い考えですか?
- 8. DataTableオブジェクトをasp.netセッションに格納するのは悪い考えです。
- 9. Rails:悪い考え:手動でセッションクッキーを作成する
- 10. なぜループの内部は悪い考えですか?
- 11. <body>要素のシャドウDOMは悪い考えですか?
- 12. プロローグの初心者 - これは悪い考えですか?
- 13. indexeddbコマンドの連鎖は悪い考えですか?
- 14. これはリモート接続には悪い考えですか?
- 15. javascript配列のDOMオブジェクトやjQueryオブジェクトへの参照を維持するのは悪い考えですか?
- 16. ネストされたTry/Catchブロックは悪い考えですか?
- 17. winformsアプリケーションのASP.NETメンバーシッププロバイダを悪い考えですか?
- 18. 深いクラスの継承階層 - 悪い考えですか?
- 19. スマーターセッター?良いか悪い考えですか?
- 20. テストケース内のテストケース、賢明か悪い考えですか?
- 21. ASP.NETページプロパティ良い考え方または悪い考え方
- 22. Androidで過剰なスレッディングが悪い考えですか?
- 23. 今日のHTMLメールの状況 - 悪い考えですか?
- 24. initメソッドでスレッドを開始するのは悪い考えですか?
- 25. whileループで状態を設定するのは悪い考えですか?
- 26. 要求間のキャッシュRailsモデル - 悪い考えですか?
- 27. MongoDBの疑似主キー - 悪い考えですか?
- 28. "java.library.path"のJVMリロードを強制するのは悪い考えですか?
- 29. Angular2 - レデューサー間の行動を共有するのは悪い考えですか?
- 30. サービス境界を越えて例外を渡す、悪い考えですか?
私はそれが一貫していると思います。 Pythonは、インプレース操作である可変オブジェクトのメソッドに関してかなり一貫しています。一貫性がある限り、オブジェクトまたはオブジェクト参照を返すインプレース操作の問題は発生しません。 –
しかし、なぜそれは最初の場所でそれのようですか? – asmeurer
私は100%確実ではありませんが、ほとんどの場合、オブジェクトを返すためのインプレース操作は必要ありません。結局、割り当てが必要な新しいオブジェクトを作成しているわけではありません。さらに、それぞれのインプレース操作に類似したものがあります。これにより、明示的に明白な操作を行うために何かを返すことになります。 (例えば、 'list.sort'と' sorted(list) '、' list.reverse'と 'reversed(list) ') –