2009-06-18 12 views
92

पायथन में, क्या इसे बिना कॉल किए एक अनबाउंड विधि बांधने का कोई तरीका है?पायथन: एक अनबाउंड विधि बांधें?

मैं एक wxPython कार्यक्रम लिख रहा हूँ, और एक निश्चित वर्ग मैंने तय कर लिया मेरे बटन के सभी डेटा को एक साथ tuples के एक वर्ग के स्तर के सूची के रूप में है, इसलिए की तरह समूह के लिए अच्छा होगा के लिए:

class MyWidget(wx.Window): 
    buttons = [("OK", OnOK), 
       ("Cancel", OnCancel)] 

    # ... 

    def Setup(self): 
     for text, handler in MyWidget.buttons: 

      # This following line is the problem line. 
      b = wx.Button(parent, label=text).Bind(wx.EVT_BUTTON, handler) 

समस्या यह है कि, handler के सभी मान अनबाउंड विधियां हैं, मेरा प्रोग्राम एक शानदार आग लगने में विस्फोट करता है और मैं रोता हूं।

मैं एक अपेक्षाकृत सरल, हल करने योग्य समस्या के समान समाधान के लिए ऑनलाइन देख रहा था। दुर्भाग्य से मुझे कुछ भी नहीं मिला। अभी, मैं इस पर काम करने के लिए functools.partial का उपयोग कर रहा हूं, लेकिन क्या किसी को पता है कि एक उदाहरण के लिए एक अनबाउंड विधि को बांधने के लिए एक साफ-सुथरा, स्वस्थ, पाइथोनिक तरीका है और इसे कॉल किए बिना इसे पास करना जारी रखें?

+1

परिभाषित करें "अनबाउंड विधि" – Christopher

+4

@Christopher - एक विधि है कि वस्तु से चूसा था की गुंजाइश के लिए बाध्य नहीं है, तो आप स्वयं को स्पष्ट रूप से पारित करने के लिए की है। –

उत्तर

143

सभी कार्य भी वर्णनकर्ता है, तो आप उन्हें अपने __get__ विधि को फोन करके बाध्य कर सकते हैं कर रहे हैं।

+2

यह बहुत अच्छा है। मुझे पसंद है कि आप इस प्रकार को कैसे छोड़ सकते हैं और इसके बजाय "बाध्य विधि? .f" वापस प्राप्त कर सकते हैं। – Kiv

+0

मुझे इस विधि को 'विधि टाइप' पर एक पसंद है, क्योंकि यह py3k में समान कार्य करता है, जबकि 'विधि टाइप' के तर्क थोड़ा सा बदल दिए गए हैं। – bgw

+8

और इस प्रकार, कक्षा के उदाहरणों में कार्यों को बांधने के लिए एक फ़ंक्शन: 'बाइंड = लैम्ब्डा इंस्टेंस, func, asname: setattr (उदाहरण, asname, func .__ __ (उदाहरण, उदाहरण .__ वर्ग __) प्राप्त करें)' उदाहरण: 'कक्षा ए: पास; ' ' ए = ए(); ' 'बाइंड (ए, बाइंड,' बाइंड ')' –

3

यह बाँध होगा selfhandler रहे हैं:

bound_handler = lambda *args, **kwargs: handler(self, *args, **kwargs) 

यह self कार्य करने के लिए पहले तर्क के रूप में पास करके काम करता है। object.function()function(object) के लिए सिर्फ वाक्य रचनात्मक चीनी है।

+1

हां, लेकिन यह विधि को कॉल करता है। समस्या यह है कि मुझे कॉल करने योग्य ऑब्जेक्ट के रूप में बाध्य विधि को पारित करने में सक्षम होना चाहिए। मेरे पास अनबाउंड विधि है और जिस उदाहरण के लिए मैं इसे बाध्य करना चाहता हूं, लेकिन यह पता नहीं लगा सकता कि इसे बिना किसी कॉलिंग के तुरंत कैसे रखा जाए –

+6

नहीं, ऐसा नहीं है, यह केवल विधि को कॉल करेगा bound_handler() करें। लैम्ब्डा को परिभाषित करना लैम्ब्डा को नहीं बुलाता है। –

+0

आप वास्तव में लैम्ब्डा को परिभाषित करने के बजाय 'functools.partial' का उपयोग कर सकते हैं। हालांकि, यह सही समस्या का समाधान नहीं करता है। आप अभी भी 'instancemethod' के बजाय 'function' से निपट रहे हैं। –

68

यह types.MethodType के साथ स्पष्ट रूप से किया जा सकता है। उदाहरण:

bound_handler = handler.__get__(self, MyWidget) 

यहाँ आर Hettinger उत्तम guide को वर्णनकर्ता है:

import types 

def f(self): print self 

class C(object): pass 

meth = types.MethodType(f, C(), C) # Bind f to an instance of C 
print meth # prints <bound method C.f of <__main__.C object at 0x01255E90>> 
+8

+1 यह बहुत ही बढ़िया है, लेकिन आपके द्वारा प्रदान किए गए यूआरएल पर पाइथन डॉक्स में इसका कोई संदर्भ नहीं है। –

+2

+1, मैं अपने कोड में जादू कार्यों के लिए कॉल नहीं करना पसंद करता हूं (यानी '__get__')। मुझे पता नहीं है कि आपके द्वारा पाइथन के किस संस्करण पर आपने इसका परीक्षण किया है, लेकिन पाइथन 3.4 पर, 'विधि टाइप' फ़ंक्शन दो तर्क लेता है। समारोह और उदाहरण। तो इसे 'प्रकारों में बदला जाना चाहिए। विधि प्रकार (एफ, सी()) '। –

+0

यहां यह है! उदाहरण उदाहरण विधियों को पैच करने का यह एक अच्छा तरीका है: 'wgt.flush = type.MethodType (lambda self: none, wgt) ' – Winand

7

इसमें स्वयं के साथ एक बंद करना तकनीकी रूप से कार्य को बाध्य नहीं करेगा, लेकिन यह समान (या बहुत समान) अंतर्निहित समस्या को हल करने का एक वैकल्पिक तरीका है। यहाँ एक तुच्छ उदाहरण है:

self.method = (lambda self: lambda args: self.do(args))(self) 
संबंधित मुद्दे