2009-11-20 13 views
9

यहां एक अजगर सत्र है।मेटाक्लास को उप-वर्गों में नहीं कहा जा रहा है

>>> class Z(type): 
    def __new__(cls, name, bases, attrs): 
     print cls 
     print name 
     return type(name, bases, attrs) 
...  
>>> class Y(object): 
    __metaclass__ = Z 
...  
<class '__main__.Z'> 
Y 
>>> class X(Y): 
...  pass 
... 
>>> class W(Y): 
...  __metaclass__ = Z 
...  
<class '__main__.Z'> 
W 
>>> 

बाद मैं परिभाषित ग्यारहवीं कक्षा की उम्मीद Z._new__ इसके लिए कहे जाने के, और दो लाइन है, जो नहीं हो रहा है, (रूप metaclass विरासत में मिला रहे हैं?) मुद्रित करने के लिए

उत्तर

12

समस्या है cls तर्क (जो मेटाक्लास ऑब्जेक्ट है) जब आप type पर कॉल करते हैं, तो क्लास ऑब्जेक्ट Y जिसे बनाया और लौटाया गया है, मेटाक्लास Z का कोई संदर्भ नहीं है।

आप

return super(Z, cls).__new__(cls, name, bases, attrs) 

साथ __new__ में अंतिम पंक्ति की जगह तो यह काम करता है। ध्यान दें कि cls का उपयोग super में किया जाता है, फिर भी हमें cls को एक तर्क के रूप में भी प्रदान करना होगा, क्योंकि super यहां एक अनबाउंड विधि लौटाता है (अधिक के लिए here देखें)।

इस्तेमाल कर सकते हैं सुपर एक का उपयोग करने के लिए एक विकल्प के रूप:

return type.__new__(cls, name, bases, attrs) 

महत्वपूर्ण बात यह है कि हम classmethod __new__ को cls (हमारे metaclass वस्तु Z) देना है। छोटे फॉर्म type(name, bases, attrs)type में cls तर्क के लिए स्वयं भर जाता है, जो निश्चित रूप से गलत है। यह त्रुटि गलत उदाहरण self तर्क के साथ एक उदाहरण विधि को कॉल करने के समान है।

मैं super का उपयोग करना पसंद करता हूं, क्योंकि यह बेहतर शैली है।

+2

आह, ठीक है, वह काम। लेकिन 'सुपर (जेड, सीएलएस) वापस नहीं करना चाहिए .__ new__' 'टाइप .__ वर्ग __ के बराबर हो। नया' whis 'टाइप .__ new__' के बराबर है जो' टाइप' के माध्यम से एक नई कक्षा बनाने के समान होना चाहिए? – agiliq

+2

यह वास्तव में वही नहीं है, अब मैं इसे अपने उत्तर में संबोधित करता हूं। सुपर 'टाइप .__ new__' विधि को कॉल करता है, लेकिन फिर हम सही' cls' तर्क का उपयोग कर सकते हैं, जो संभव नहीं है अगर हम सीधे 'टाइप'' कहते हैं। – nikow

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