2012-10-25 5 views
19

ここではPythonについて話していますが、これはおそらくほとんどの言語に当てはまると思います。私が可変オブジェクトを持っている場合、インプレース操作でもオブジェクトを返すのは悪い考えですか?ほとんどの例のように、オブジェクトを修正してNoneを返すようです。たとえば、list.sortです。インプレース操作でオブジェクトを返すのは悪い考えですか?

+0

私はそれが一貫していると思います。 Pythonは、インプレース操作である可変オブジェクトのメソッドに関してかなり一貫しています。一貫性がある限り、オブジェクトまたはオブジェクト参照を返すインプレース操作の問題は発生しません。 –

+0

しかし、なぜそれは最初の場所でそれのようですか? – asmeurer

+2

私は100%確実ではありませんが、ほとんどの場合、オブジェクトを返すためのインプレース操作は必要ありません。結局、割り当てが必要な新しいオブジェクトを作成しているわけではありません。さらに、それぞれのインプレース操作に類似したものがあります。これにより、明示的に明白な操作を行うために何かを返すことになります。 (例えば、 'list.sort'と' sorted(list) '、' list.reverse'と 'reversed(list) ') –

答えて

25

はい、悪い考えです。その理由は、インプレース操作と非インプレース操作が明らかに同じ出力を持つ場合、プログラマは、インプレース操作と非インプレース操作(List.sort()sorted())を頻繁に混在させ、エラーを検出する。

自分自身を返すインプレース操作では、メソッドチェーニングを実行できますが、偶然にチェーンの途中に副作用のある関数を埋め込む可能性があるため、これは悪い方法です。

このようなエラーを防ぐには、メソッドチェーンには副作用を持つメソッドが1つしかなく、その関数はチェーンの最後にある必要があります。チェーン内のそれ以前の関数は、副作用なしに入力を変換する必要があります(例えば、ツリーのナビゲート、文字列のスライスなど)。インプレース操作が自分自身に戻ると、プログラマーはコピーを返す代替関数の代わりに誤って使用することになり、副作用(List.sort()sorted())がなくなり、エラーが発生しやすくなりますデバッグ。

これは、Pythonの標準ライブラリ関数が常にコピーを返すかNoneを返して、オブジェクトをインプレースで修正しますが、インプレースでオブジェクトを変更したり、自分自身を戻したりすることがないためです。 Djangoのような他のPythonライブラリもこの方法に従います(Djangoについてはthis very similar questionを参照してください)。

+0

原則として合意しましたが、私は例外があると思います。 Eg1:メソッドのセマンティックが、jQueryの '.empty()'のように、適切な操作である場合。 Eg2:APIが非常に一般的に使用されているため、初心者から始めて知り、jQueryの '.append() 'のようなコピーを返すバージョンはありません –

+0

メソッド名が現在の時制動詞なので、操作がインプレースで動作することを人々が明らかにすることを意味します。私はいつも 'list.sort'がインプレースで動いていたことを思い出す前に、Pythonを学んだ後、長い時間がかかりました。 – asmeurer

+0

インプレース操作でチェーンを終了することとまだ混乱していませんか? 'a.sort()'と 'a [:2] .sort()'は全く違うことをしようとしています(ビューを使うnumpy 'array'のようなものを使うと違うでしょう)。たぶんポイントは、 'sort'が' None'を返すことは、 'a [:2] .sort()'が役に立つと思うことからあなたを守りますか? – asmeurer

0

ユースケースによって異なると思われます。私は、結果を使用しない以外に、インプレース操作からオブジェクトを戻すのが痛いのはなぜか分かりませんが、あなたが純粋な機能主義について非常に慎重でない場合は、実際には問題にはなりません。 jQueryのような呼び出し連鎖パターンが好きなので、関数を使用したときに関数がそれを返したときにはそれを感謝します。

8

変更されたオブジェクトを修正したメソッドから戻すと、いくつかの利点がありますが、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を返すのをやめてください。このルールを破ることは時には便利なことがあることに注意してください。

+1

優れた答え、特にコマンド/クエリ分離原則へのリンクをありがとう私は最近迷っているデザインのトレードオフにラベルをつけています。 – FMc

関連する問題