2012-09-16 13 views
14

मान लीजिए निम्नलिखित वर्ग:क्यों __getitem__ क्लासमेड नहीं हो सकता है?

class Class(object): 
    @classmethod 
    def getitem(*args): 
     print 'getitem %s' % (args,) 
    @classmethod 
    def __getitem__(*args): 
     print '__getitem__ %s' % (args,) 

GetItem विधि बर्ताव करता है के रूप में उम्मीद: यह पहली बार आर्ग के रूप में Class प्राप्त करता है, लेकिन __getitem__ पहले आर्ग के रूप में प्राप्त करता है type:

calling Class.getitem(test) 
getitem (<class '__main__.Class'>, 'test') 

calling obj.getitem(test) 
getitem (<class '__main__.Class'>, 'test') 

calling Class[test] 
'type' object has no attribute '__getitem__' 

calling obj[test] 
__getitem__ (<class '__main__.Class'>, 'test') 

क्या __getitem__ के पीछे वहाँ जादू है?

उत्तर

18

विशेष तरीकों उदाहरण पर नहीं वर्ग पर देखा जाता है, और - नियमित तरीकों कि उदाहरण पर देखा जाता है के विपरीत प्रथम। पाइथन डेटा मॉडल दस्तावेज़ों में Special method lookup देखें।

Class के बारे में type का एक उदाहरण के रूप में सोच रही थी, इसका अर्थ है कि

Class.getitem(test) 

यह वास्तव में क्या आप यह कहना के लिए पहले लग रहा है कार्य करें: Class की खुद की विशेषताओं में एक विधि getitem कहा जाता है। लेकिन, जब तुम

Class[test] 

का उपयोग यह इस को छोड़ देता है, और type के लिए सीधे चला जाता है (Class, या उसके metaclass के वर्ग जा रहा है), और इसलिए type.__getitem__(Class, test) कहता है। तो, क्या हो रहा है यह नहीं है कि __getitem__type को अपने पहले तर्क के रूप में प्राप्त होता है (यह अभी भी Class प्राप्त होगा, जैसा कि आप स्पष्ट रूप से Class.__getitem__(test)) करते हैं, यह __getitem__ है कि इस मामले में पाइथन दिखता है। इसे अस्तित्व में लाने के लिए, आपको Class के लिए अपना स्वयं का मेटाक्लास सेट करना होगा जो इसे Class पर क्लासमेड के रूप में परिभाषित करने के बजाय इसे एक उदाहरण विधि के रूप में परिभाषित करता है।

+0

'कक्षा के प्रकार के उदाहरण के रूप में सोच रहा है'। धन्यवाद। धन्यवाद। धन्यवाद। – norbertpy

9

जब आप x[test] पर कॉल करते हैं, तो दुभाषिया विशेषता के लिए type(x) का निरीक्षण करता है। Class[test] के मामले में यह Class का मेटाक्लास है, यानी type। यदि आप कक्षा-व्यापी __getitem__ रखना चाहते हैं, तो इसे एक नए मेटाक्लास के अंदर परिभाषित करें। (कहने की जरूरत नहीं, कि जादू का एक प्रकार है, कुछ भी रूप में आप metaclasses के साथ क्या)

class Meta(type): 
    def __getitem__(self, arg): 
     print "__getitem__:", arg 


class X(object): 
    __metaclass__ = Meta 

X['hello'] # output: __getitem__ hello 
+0

प्रश्नों के समाधान के लिए Thats का समाधान कहा गया है, लेकिन यह इस तरह के वाक्य रचनात्मक चीनी के लिए बहुत अधिक कोडिंग है। और वास्तविक कोड में मैं मेटाक्लास पर __getitem__ को आजमाने की कोशिश कर रहा हूं :) – qMax