2017-01-23 5 views
8

चेनिंग मैं इस method chaining in python पाया, लेकिन फिर भी इसके साथ मैं अजगर में विधि श्रृंखलन नहीं समझ सके।बुनियादी विधि

यहाँ लक्ष्यों दो हैं: कोडिंग समस्या का समाधान और विधि श्रृंखलन समझते हैं (यह देखते हुए कि मैं अभी भी callables साथ% नहीं 100 आश्वस्त हूँ)।

समस्या परिभाषा के लिए नीचे।

मैं एक वर्ग दो विधियों है कि चाहते हैं: एक वस्तु = 'लाइन' और 'बार' के लिए अन्य अधिलेखित कर देता है की एक पैरामीटर तय करता है।

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() रिटर्न के लिए .second_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') 

नोट, हालांकि, यह है कि आप कुछ भी नहीं के ऊपर लिख, संशोधन inplace काम नहीं करता है (जो यकीनन अच्छा है, Btw)। वैसे भी, यह वास्तविक दुनिया के मामलों के लिए एक अच्छी डिजाइन पसंद की तरह नहीं दिखता है, क्योंकि किसी बिंदु पर आपके तरीकों के लिए तर्क की आवश्यकता होगी।

संबंधित मुद्दे