2010-09-23 6 views
17

पायथन सजावट करने के लिए मजेदार हैं, लेकिन ऐसा लगता है कि सजावट करने वालों के तर्कों के कारण मुझे दीवार पर मारा गया है। यहां मेरे पास बेस क्लास के हिस्से के रूप में परिभाषित एक सजावटी है (सजावटी कक्षा के सदस्यों तक पहुंच जाएगा इसलिए इसे स्वयं पैरामीटर की आवश्यकता होगी)।आधार वर्ग का हिस्सा हैं जो पाइथन सजावट का उपयोग विरासत कक्षाओं में सदस्य कार्यों को सजाने के लिए नहीं किया जा सकता है

class SubSystem(object): 
    def UpdateGUI(self, fun): #function decorator 
     def wrapper(*args): 
      self.updateGUIField(*args) 
      return fun(*args) 
     return wrapper 

    def updateGUIField(self, name, value): 
     if name in self.gui: 
      if type(self.gui[name]) == System.Windows.Controls.CheckBox: 
       self.gui[name].IsChecked = value #update checkbox on ui 
      elif type(self.gui[name]) == System.Windows.Controls.Slider: 
       self.gui[name].Value = value # update slider on ui 

     ... 

मैंने बाकी कार्यान्वयन को छोड़ दिया है। अब यह वर्ग विभिन्न उप-प्रणालियों के लिए एक बेस क्लास है जो इसके उत्तराधिकारी होंगे - कुछ विरासत वाले वर्गों को अपडेटगुआई सजावट का उपयोग करने की आवश्यकता होगी।

class DO(SubSystem): 
    def getport(self, port): 
     """Returns the value of Digital Output port "port".""" 
     pass 

    @SubSystem.UpdateGUI 
    def setport(self, port, value): 
     """Sets the value of Digital Output port "port".""" 
     pass 

एक बार फिर मैंने फ़ंक्शन कार्यान्वयन को छोड़ दिया है क्योंकि वे प्रासंगिक नहीं हैं।

unbound method UpdateGUI() must be called with SubSystem instance as first argument (got function instance instead)

:

कम समस्या में है कि जब मैं SubSystem.UpdateGUI के रूप में यह specifiying द्वारा डेकोरेटर विरासत में मिला वर्ग से आधार वर्ग में परिभाषित का उपयोग कर सकते हैं, मैं अंत में इस लेखन त्रुटि जब इसका इस्तेमाल करने की कोशिश कर मिलता है

ऐसा इसलिए है क्योंकि मेरे पास सजावट करने के लिए self पैरामीटर को पारित करने का कोई तत्काल पहचान योग्य तरीका नहीं है!

क्या ऐसा करने का कोई तरीका है? या क्या मैं पाइथन में वर्तमान सजावटी कार्यान्वयन की सीमा तक पहुंच गया हूं?

उत्तर

17

आपको UpdateGUI@classmethod बनाने की आवश्यकता है, और wrapper को self से अवगत कराएं। एक काम कर उदाहरण:

class X(object): 
    @classmethod 
    def foo(cls, fun): 
     def wrapper(self, *args, **kwargs): 
      self.write(*args, **kwargs) 
      return fun(self, *args, **kwargs) 
     return wrapper 

    def write(self, *args, **kwargs): 
     print(args, kwargs) 

class Y(X): 
    @X.foo 
    def bar(self, x): 
     print("x:", x) 

Y().bar(3) 
# prints: 
# (3,) {} 
# x: 3 
+0

यह काम किया! कभी भी सजावटी को एक वर्ग के तरीके में बदलने का विचार नहीं किया होता। – Aphex

+1

भविष्य के संदर्भ के लिए, यह वास्तव में def UpdateGUI (स्वयं, मजेदार) से पहले @classmethod जोड़कर एक पंक्ति तय किया गया था। – Aphex

+0

@ एफेक्स। केनीटीएम के रूप में आपको 'सीएलएस' के उपयोग से 'स्वयं' के उपयोग को प्रतिस्थापित करना चाहिए। यह आपके कोड को पढ़ने के लिए बहुत आसान बना देगा। – aaronasterling

2

आपको सजावट करने के लिए SubSystem का उदाहरण उपयोग करने की आवश्यकता है या classmethod का उपयोग केनी के सुझाव के रूप में करें।

subsys = SubSystem() 
class DO(SubSystem): 
    def getport(self, port): 
     """Returns the value of Digital Output port "port".""" 
     pass 

    @subsys.UpdateGUI 
    def setport(self, port, value): 
     """Sets the value of Digital Output port "port".""" 
     pass 

आप तय तय करने से ऐसा करने के लिए जो अगर आप एक ही जीयूआई इंटरफेस साझा करने के लिए सभी उपवर्ग उदाहरणों चाहते हैं या यदि आप विशिष्ट लोगों को अलग इंटरफेस है यह बताने के लिए सक्षम होना चाहते हैं।

यदि वे सभी एक ही जीयूआई इंटरफ़ेस साझा करते हैं, तो क्लास विधि का उपयोग करें और सजावटी को क्लास इंस्टेंस का उपयोग करने वाली हर चीज बनाएं।

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

+0

यह काम कर सकता है लेकिन सजावटी को कॉल करने के लिए बेस क्लास का सिंगलटन उदाहरण बनाना एक बुरा विचार है। अन्य चीजों के अलावा, 'स्वयं' सजावटी और अन्य तरीकों के भीतर विभिन्न वस्तुओं को संदर्भित करेगा। फिर आपको उस ऑब्जेक्ट को तुरंत चालू करना होगा जिसे आप नहीं चाहते हैं। इसके बजाय, अन्य उत्तरों में सुझाए गए अन्य विकल्पों का चयन करें, जैसे staticmethod या classmethod को परिभाषित करना। – vokimon

3

यह सिर्फ SubSytem कक्षा से बाहर डेकोरेटर खींचने के लिए आसान हो सकता है: (ध्यान दें कि मैं यह सोचते हैं रहा है कि self कि setport कॉल एक ही self है कि आप करने के लिए उपयोग करना चाहते हैं updateGUIField फोन)

def UpdateGUI(fun): #function decorator 
    def wrapper(self,*args): 
     self.updateGUIField(*args) 
     return fun(self,*args) 
    return wrapper 

class SubSystem(object): 
    def updateGUIField(self, name, value): 
     # if name in self.gui: 
     #  if type(self.gui[name]) == System.Windows.Controls.CheckBox: 
     #   self.gui[name].IsChecked = value #update checkbox on ui 
     #  elif type(self.gui[name]) == System.Windows.Controls.Slider: 
     #   self.gui[name].Value = value # update slider on ui 
     print(name,value) 

class DO(SubSystem): 
    @UpdateGUI 
    def setport(self, port, value): 
     """Sets the value of Digital Output port "port".""" 
     pass 

do=DO() 
do.setport('p','v') 
# ('p', 'v') 
+0

निश्चित रूप से, मेरे पास मेरे प्रोजेक्ट में अन्य सजावटी हैं जो बस अपने आप बैठते हैं और मैं उन्हें आवश्यकतानुसार आयात करता हूं। हालांकि चूंकि यह सजावट एक उदाहरण विशिष्ट सदस्य (self.updateGUIField) का उपयोग करता है, इसे कक्षा का हिस्सा होना चाहिए। – Aphex

+1

@ एफेक्स: क्या आपने मेरा कोड आजमाया? मुझे लगता है कि सजावट के बिना कक्षा का हिस्सा होने के बावजूद यह ठीक काम करता है। – unutbu

+0

यह शायद युग्मन चाहता है कि युग्मन को तोड़ देता है। 'UpdateGUI 'को' सबसिस्टम '(या' सबसिस्टम 'के उप-वर्गों के संदर्भ में बुलाए बिना कोई अर्थ नहीं है, इसलिए यह एक स्थिर या वर्ग विधि होना चाहिए। – cowbert

3

आप इन सबसे छुटकारा पाना पूछ में प्रश्न का उत्तर दिया:। क्या तर्क आप self के रूप में प्राप्त करने के लिए अगर आप SubSystem.UpdateGUI फोन उम्मीद करेंगे? एक स्पष्ट उदाहरण नहीं है जिसे सजावटी को पास किया जाना चाहिए।

ऐसी कई चीजें हैं जो आप इसके आसपास पाने के लिए कर सकते हैं। हो सकता है कि आपके पास पहले से subSystem है जिसे आपने कहीं और तुरंत चालू कर दिया है? तो फिर तुम अपने डेकोरेटर इस्तेमाल कर सकते हैं:

subSystem = SubSystem() 
subSystem.UpdateGUI(...) 

लेकिन हो सकता है आप, बस वर्गSubSystem पहली जगह में उदाहरण जरूरत नहीं थी? उस मामले में, classmethod डेकोरेटर का उपयोग अजगर बताने के लिए है कि इस समारोह एक उदाहरण के बजाय पहले तर्क के रूप में अपने वर्ग प्राप्त करना चाहिए:

@classmethod 
def UpdateGUI(cls,...): 
    ... 

अंत में, हो सकता है आप का उपयोग या तो उदाहरण या वर्ग की जरूरत नहीं है ! उस मामले में, staticmethod का उपयोग करें:

@staticmethod 
def UpdateGUI(...): 
    ... 

ओह, वैसे, अजगर सम्मेलन कक्षाओं के लिए केमलकेस नाम आरक्षण है और उस वर्ग पर तरीकों के लिए mixedCase या under_scored नाम का उपयोग करने के लिए।

+0

@Aaron: सच, धन्यवाद। – katrielalex

+0

@ self.UpdateGUI काम नहीं करता है, क्योंकि वर्ग परिभाषा के दायरे में स्वयं का कोई अर्थ नहीं है। यही कारण है कि मैंने बेस क्लास का नाम इस्तेमाल किया। – Aphex

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