2017-01-23 14 views
8

私はこれを見つけましたが、たとえそれであっても、Pythonのメソッド連鎖を理解できませんでした。基本的なメソッド連鎖

ここで目標は2つです。コーディングの問題を解決し、メソッド連鎖を理解します(私は依然として100%自信を持って呼び出し可能です)。

問題の定義に至るまで。

2つのメソッドを持つクラスが必要です.1つはobject = 'line'のパラメータを設定し、もう1つは 'bar'に上書きします。

これは私がこれまでに得たものである:

class foo(): 
    def __init__(self, kind=None): 
     self.kind = kind 

    def __call__(self, kind=None): 
     return foo(kind=kind) 

    def my_print(self): 
     print (self.kind) 

    def line(self): 
     return self(kind='line') 
    def bar(self): 
     return self(kind='bar') 

悲しいことに、このコードで、私はこの

a = foo() 
a.bar().line().bar().bar().line().my_print() 

をやって私の目標を達成することができます。しかし、私はこれを書くことで同じ結果を得るしたいと思いますコード

a = foo() 
a.bar.line.bar.bar.line.my_print() 

どうすればよいですか?私は__call__メソッドをどのように定義したのか何か間違っていると思います。あなたの助けを前にありがとう。

答えて

18

を返すことができるのは、単に.first_func()が返すメソッドチェーンだけです。すべての連鎖可能メソッドがselfを返すようにすることで、かなり簡単に実装されます。 (これは__call()__とは関係ありません)。

class foo(): 
    def __init__(self, kind=None): 
     self.kind = kind 
    def my_print(self): 
     print (self.kind) 
     return self 
    def line(self): 
     self.kind = 'line' 
     return self 
    def bar(self): 
     self.kind='bar' 
     return self 

あなたは彼らの戻り値を無視することによって非チェーン方法でfooオブジェクトを使用することができます。

a = foo() 
a.line() 
a.my_print() 
a.bar() 
a.my_print() 

assert a.kind == 'bar' 

あるいは、すべての機能は今、オブジェクト自体を返すために、あなたが返さ上で直接 を操作することができます値。あなたはこの同等のコードと連鎖する方法を使用することができます。

b = foo() 
b.line().my_print().bar().my_print() 
assert b.kind == 'bar' 

あるいは:

c = foo().line().my_print().bar().my_print() 
assert c.kind == 'bar' 

()呼び出し構文を取り除くの質問は、メソッドチェーンから完全に別の概念です。チェーンプロパティが必要な場合は、これらのプロパティをオブジェクトに変更してください。@propertyデコレータを使用してください。 (しかし、プロパティを経由してオブジェクトを変異することは、危険と思われるより良い方法を使用して、動詞とそれに名前を付ける:。.set_line()代わりの.line、例えば。)非常に徹底的な答えを

class foo(): 
    def __init__(self, kind=None): 
     self.kind = kind 
    def my_print(self): 
     print (self.kind) 
     return self 
    @property 
    def line(self): 
     self.kind = 'line' 
     return self 
    @property 
    def bar(self): 
     self.kind='bar' 
     return self 

a = foo() 
a.line 
a.my_print() 
a.bar 
a.my_print() 

assert a.kind == 'bar' 

b = foo() 
b.line.my_print().bar.my_print() 
assert b.kind == 'bar' 

c = foo().line.my_print().bar.my_print() 
assert c.kind == 'bar' 
+0

感謝!! – Pezze

3

プロパティ(記述子)を使用します。

class foo: 
    def __init__(self, kind=None): 
     self.kind = kind 

    def __call__(self, kind=None): 
     return foo(kind=kind) 

    def my_print(self): 
     print (self.kind) 

    @property 
    def line(self): 
     return self(kind='line') 

    @property 
    def bar(self): 
     return self(kind='bar') 

注意、しかし、あなたは何を上書きしないことを、変更が(ところで、間違いなく良いです)、インプレースを動作しません。とにかく、ほとんどの現実的なケースでは、これは良い設計選択肢のようには見えません。

関連する問題