web-dev-qa-db-ja.com

クラスメソッドから「return self」の目的は?

私はオープンソースプロジェクトでこのようなものに出会いました。インスタンス属性を変更するメソッドは、インスタンスへの参照を返します。この構成の目的は何ですか?

class Foo(object):

  def __init__(self):
    self.myattr = 0

  def bar(self):
    self.myattr += 1
    return self
46
nate c

連鎖を可能にするためです。

例えば:

var Car = function () {
    return {
        gas : 0,
        miles : 0,
        drive : function (d) {
            this.miles += d;
            this.gas -= d;
            return this;
        },
        fill : function (g) {
            this.gas += g;
            return this;
        },
    };
}

今あなたは言うことができます:

var c = Car();
c.fill(100).drive(50);
c.miles => 50;
c.gas => 50;
66
Josh K

@Lie Ryanと@Frank Sheararが言及しているように、これは「滑らかなインターフェース」と呼ばれていますが、そのパターンは非常に長い間存在しています。

そのパターンの物議を醸している部分は、オブジェクト指向では変更可能な状態であるため、voidメソッドには一種の暗黙の戻り値thisがあります。つまり、状態が更新されたオブジェクトは戻り値の一種です。

したがって、OO変更可能な状態の言語では、これら2つはほぼ同等です。

a.doA()
a.doB()
a.doC()

...とは対照的に

a.doA().doB().doC()

ですから、私は過去の人々が最初のフォームが好きなので、流暢なインターフェースに抵抗するのを聞いたことがあります。私が「流暢なインターフェース」で聞いたもう1つの名前は、「列車事故」です;)

流暢なインターフェイスはしわを追加するため、私は「多かれ少なかれ同等」と言います。彼らは「これを返す」必要はありません。彼らは「新しいものを返す」ことができます。これは、OOで不変オブジェクトを取得する方法です。

だからあなたは(疑似コード)を行うクラスAを持つことができます

function doA():
    return new A(value + 1)

function doB():
    return new A(value * 2)

function doC():
    return new A(sqrt(value))

ここで、各メソッドは新しいオブジェクトを返し、初期オブジェクトは変更しません。これは、コードをあまり変更せずに不変オブジェクトにアクセスする方法です。

10
Rob

ほとんどの言語は 'return self'イディオムを認識しており、それが行で使用されていない場合は無視します。ただし、Pythonでは、関数がデフォルトでNoneを返すことに注意してください。

私がCSスクールにいたとき、私のインストラクターは関数、手順、ルーチン、メソッドの違いについてhugeを扱いました。筆記用のエッセイの質問の多くは、シャープペンシルが私の手に熱くなっていることで解決されました。

言うだけで十分です、自分自身を返すことは、クラスメソッドを作成する決定的な方法ですOO方法ですが、Pythonは、複数の戻り値、タプル、リスト、オブジェクト、プリミティブを許可します、またはなし。

彼らが言うように、チェーンは、最後の操作に対する答えを次の操作に単に入れているだけであり、Pythonのランタイムは、そのようなことを最適化できます。リスト内包表記は、これ(非常に強力です!)

したがって、Pythonでは、すべてのメソッドまたは関数が返すことはそれほど重要ではないため、デフォルトはNoneです。

プログラム内のすべてのアクションは、その成功、失敗、または結果を呼び出し側のコンテキストまたはオブジェクトに報告するべきであるという考え方がありますが、ここではDOD ADA要件について話していませんでした。メソッドからフィードバックを取得する必要がある場合は、先に進むかどうかにかかわらず、一貫性を保つようにしてください。

メソッドが失敗する可能性がある場合、成功または失敗を返すか、処理する例外を発生させる必要があります。

注意点の1つは、return selfイディオムを使用する場合、Pythonを使用すると、すべてのメソッドを変数に割り当てることができ、実際に取得しているときにデータ結果またはリストを取得していると思うかもしれません。オブジェクト。

型を制限する言語は、これを実行しようとすると、叫び声を上げて叫び、壊れますが、解釈された言語(Python、Lua、LISP)は、はるかに動的です。

8
Chris Reid

Smalltalkでは、明示的に何かを返さないすべてのメソッドに、暗黙の「return self」があります。

これは、(a)すべてのメソッドが何かを返すことでコンピューティングモデルがより均一になること、および(b)メソッドが自分自身を返すことは非常に役立つためです。ジョシュKは素晴らしい例を挙げています。

4
Frank Shearar

オブジェクトを返す長所(return self

  • 例:

    print(foo.modify1().modify2())
    
    # instaed of
    foo.modify1()
    foo.modify2()
    print(foo)
    
  • プログラミングコミュニティでより人気のあるスタイル(私は思う)。

オブジェクトを変更する利点(return selfなし)

  • 他の目的でreturnを使用する機能。
  • Guido van Rossumこのスタイルの承認 (私は彼の主張に同意しません)。
  • Pythonコミュニティでより人気のあるスタイル(と思います)。
  • デフォルト(より少ないソースコード)。
2
xged