मैं अजगर में एक समस्या है, जिसके लिए मैं किसी भी स्वच्छ समाधान नहीं मिल सकता है ...पायथन: metaclass + लिपटे तरीकों + विरासत = समस्याओं
जब कुछ तरीकों बुला, मैं विधि क्रियान्वयन से पहले कुछ कोड निष्पादित करने के लिए चाहते हैं और बाद में। context
चर स्वचालित रूप से सेट और साफ़ करने के क्रम में (कई अन्य चीजों के बीच)। ,
class Parent(object):
__metaclass__ = MyType
def test(self):
#Here the context is set:
print self.context #prints blabla
लेकिन जैसे ही मैं Parent
उपवर्ग करना चाहते हैं के रूप में, समस्याओं दिखाई देते हैं:
class MyType(type):
def __new__(cls, name, bases, attrs):
#wraps the 'test' method to automate context management and other stuff
attrs['test'] = cls.other_wrapper(attrs['test'])
attrs['test'] = cls.context_wrapper(attrs['test'])
return super(MyType, cls).__new__(cls, name, bases, attrs)
@classmethod
def context_wrapper(cls, operation):
def _manage_context(self, *args, **kwargs):
#Sets the context to 'blabla' before the execution
self.context = 'blabla'
returned = operation(self, *args, **kwargs)
#Cleans the context after execution
self.context = None
return returned
return _manage_context
@classmethod
def other_wrapper(cls, operation):
def _wrapped(self, *args, **kwargs):
#DO something with self and *args and **kwargs
return operation(self, *args, **kwargs)
return _wrapped
यह एक आकर्षण की तरह काम करता है:
इस लक्ष्य को हासिल करने के लिए, मैं निम्नलिखित metaclass घोषणा की है जब मैं super
के साथ मूल विधि को कॉल करता हूं:
class Child(Parent):
def test(self):
#Here the context is set too
print self.context #prints blabla
super(Child, self).test()
#But now the context is unset, because Parent.test is also wrapped by _manage_context
#so this prints 'None', which is not what was expected
print self.context
मैंने इसे नए मान पर सेट करने से पहले संदर्भ को सहेजने का विचार किया है, लेकिन यह केवल आंशिक रूप से समस्या हल करता है ...
दरअसल, (लटकाओ, यह समझाना मुश्किल है), मूल विधि कहा जाता है, रैपर क्रियान्वित कर रहे हैं, लेकिन वे *args
प्राप्त करते हैं और **kwargs
Parent.test
को संबोधित करते हुए self
एक Child
उदाहरण है, इसलिए self
विशेषताओं अप्रासंगिक मान हो अगर मैं उन्हें *args
और **kwargs
(स्वचालित सत्यापन प्रयोजन के लिए उदाहरण के लिए) के साथ चुनौती देना चाहते हैं, उदाहरण के:
@classmethod
def validation_wrapper(cls, operation):
def _wrapped(self, *args, **kwargs):
#Validate the value of a kwarg
#But if this is executed because we called super(Child, self).test(...
#`self.some_minimum` will be `Child.some_minimum`, which is irrelevant
#considering that we called `Parent.test`
if not kwarg['some_arg'] > self.some_minimum:
raise ValueError('Validation failed')
return operation(self, *args, **kwargs)
return _wrapped
तो मूल रूप से, हल करने के लिए ई इस समस्या को मैं दो समाधान देखें:
रैपर को रोकने निष्पादित करने के लिए जब विधि
super(Child, self)
एक
self
"सही" प्रकार की हमेशा होता है कि होने के साथ बुलाया गया था
दोनों समाधान मेरे लिए असंभव प्रतीत होते हैं ... क्या किसी को यह हल करने का विचार है? एक सुझाव ?
आप इसके लिए सजावट का उपयोग क्यों नहीं कर सकते? –
क्या आप पाइथन में किसी प्रकार के पहलू उन्मुख प्रोग्रामिंग समर्थन की तलाश में हैं? इसके लिए कुछ विचारों के लिए http://stackoverflow.com/questions/286958/any-aop-support-library-for-python देखें। यह वही नहीं है जो आप पूछ रहे हैं, बल्कि यह आपकी मूल जरूरतों को हल करने की कोशिश कर रहा है। – Makis
@ Space_C0wb0y: क्योंकि मैं 5 सजावटकर्ताओं के साथ पुनर्व्यवस्थित किए बिना, सबक्लास में 'टेस्ट' को फिर से चलाने में सक्षम होना चाहता हूं! और वैसे भी जो मेरी समस्या का समाधान नहीं करेंगे: जिस तरह से मैं मेटाक्लास से विधियों को लपेटता हूं वह सजावट करने वालों के बराबर है। – sebpiq