2011-08-11 5 views
30

में examplemethods में विशेषताओं को जोड़ना कक्षा-सजावट करने वाले और विधि-सजावटी को अच्छी तरह से खेलने के लिए प्रयास करते समय मैं इस व्यवहार में घुस गया। अनिवार्य रूप से, विधि सजावटी कुछ विधियों को विशेष रूप से कुछ डमी मूल्य के साथ ध्वजांकित करेंगे, और कक्षा सजावट बाद में मूल्य में भर जाएगा और बाद में मूल्य भर जाएगा। इस सरल उदाहरण हैपायथन

>>> class cow: 
>>>  def moo(self): 
>>>   print 'mooo' 
>>>  moo.thing = 10 
>>> 
>>> cow.moo.thing 
10 
>>> cow().moo.thing 
10 
>>> cow.moo.thing = 5 
AttributeError: 'instancemethod' object has no attribute 'thing' 
>>> cow().moo.thing = 5 
AttributeError: 'instancemethod' object has no attribute 'thing' 
>>> cow.moo.__func__.thing = 5 
>>> cow.moo.thing 
5 

किसी को भी क्यों cow.moo.thing = 5 काम नहीं करता है पता है, भले ही cow.moo.thing काफी स्पष्ट रूप मुझे 10 देता है? और क्यों cow.moo.__func__.thing = 5 काम करता है? मुझे नहीं पता कि यह क्यों करता है, लेकिन dir(cow.moo) सूची में सामान के साथ यादृच्छिक रूप से झुकाव में कुछ काम करने की कोशिश कर रहा है, और मुझे नहीं पता कि क्यों।

उत्तर

33

विशेषता लुकअप के लिए, पायथन स्वचालित रूप से आपके लिए इंस्टेंस विधि से जुड़े वास्तविक फ़ंक्शन का उपयोग कर रहा है।

विशेषता सेटिंग के लिए, यह नहीं है।

वे आपके द्वारा दिए गए कथन के किनारे के आधार पर दो अलग-अलग संचालन हैं, भले ही वे दोनों . ऑपरेटर का उपयोग करें।

जब आप किसी इंस्टेंस विधि के __func__ तक पहुंचते हैं, तो आप वास्तव में वास्तविक फ़ंक्शन तक पहुंच रहे हैं जिसमें वास्तव में moo विशेषता है।

पायथन 3 में यह काम करेगा जैसा कि आप चाहेंगे/अपेक्षा करते हैं कि विधियां मूल रूप से केवल कार्य करती हैं।

+0

आह ठीक है, मैं कभी नहीं जानता था। धन्यवाद! –

+0

पुरानी पोस्ट को पुनर्जीवित करने के लिए खेद है लेकिन पायथन 3 'गाय() में। Moo.thing = 5' वापस लौट रहा है' विशेषता त्रुटि: 'विधि' ऑब्जेक्ट में कोई विशेषता नहीं है 'चीज़'। तुम जानते हो क्यों ? –

+0

@JacquesGaudin उदाहरण पर ('गाय()। Moo') फ़ंक्शन को पायथन के किसी भी संस्करण में विधि ऑब्जेक्ट में लपेटा जाता है - अंतर वर्ग (' cow.moo') पर होता है, यह पायथन 3 में लपेटा नहीं जाता है। 'स्वयं' को फ़ंक्शन में स्वचालित रूप से पारित करने के लिए रैपिंग आवश्यक है। – agf

3

यदि आप सी से दोनों कार्यों और उदाहरण विधियों के फ़ंक्शन विशेषताओं को संशोधित करना चाहते हैं तो आपको अपने पास कॉल करने योग्य प्रकार की जांच करनी होगी।

तो तुम तो आप इसे इस जाँच कर सकते हैं यह सोचते हैं प्रतिदेय किसी प्रकार की एक PyObject है

PyObject *callable; // set to something callable 
PyObject *setting; // set to something 
if(PyMethod_Check(callable)){ 
    PyObject_SetAttrString(PyMethod_Function(callable),"attribute",setting); 
}else{ 
    PyObject_SetAttrString(callable,"attribute",setting); 
} 
... 
// and the inverse 
if(PyMethod_Check(callable){   
    if(PyObject_HasAttrString(PyMethod_Function(callable),"attribute")){ 
     PyObject_DelAttrString(PyMethod_Function(callable),"attribute"); 
    } 
    }else{ 
    if(PyObject_HasAttrString(callable,"attribute")){ 
     PyObject_DelAttrString(callable,"attribute"); 
    } 
    } 

अब कोड एजीएफ़ बाहर काम करता है अजगर के भीतर से उदाहरण तरीकों के लिए इशारा किया। यदि मैं बस इंस्टेंस विधि की विशेषता सेट करने का प्रयास करता हूं तो यह विशेषता नहीं मिलेगी कि मैंने इसे पायथन से कैसे एक्सेस करने का प्रयास किया।

मैं इस मुद्दे में भाग गया और एएफएफ के जवाब के साथ ली हाओई के सवाल ने मुझे समझने में मदद की कि मुझे क्या बदलने की जरूरत है। मैं लगा कोई इस सवाल खोजने के लिए और फिर से जवाब देंगे, जबकि कैसे सी के माध्यम से इस समस्या को हल करने के लिए की तलाश में

संपादित करें: नोट: यह अजगर 2.7.x. के लिए है पायथन 3.x विभिन्न फ़ंक्शन कॉल का उपयोग करता है।