2013-02-15 56 views
5

में "निजी" विधि के रूप में एक "निजी" विधि के साथ एक वर्ग पर विचार करें:ओवरराइड अजगर

class Foo(object): 
    def __init__(self): 
     self.__method() 
    def __method(self): 
     print('42') 

जब मैं Foo और ओवरराइड विधि __method उपवर्ग करने की कोशिश, यह देखा जा सकता है कि Foo.__method अभी भी कहा जाता है, MoreFoo.__method के बजाय।

class MoreFoo(Foo): 
    def __method(self): 
     print('41') 

>>> MoreFoo() 
42 
<__main__.MoreFoo object at 0x7fb726197d90> 

ऐसी विधि को ओवरराइड करने का तरीका क्या होगा?

+0

http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python – tacaswell

+0

ब्याज से, जहां क्या आपको यह विचार आया कि यह एक निजी चर के बराबर था? यह वास्तव में एक बुरी गलत धारणा है, और मैं इसे हर समय देखता हूं, यह नहीं जानता कि यह कहां से आता है। –

+1

@ लैटवेयर - मुझे लगता है कि यह "निजी चर और कक्षा-स्थानीय संदर्भ" नामक दस्तावेज़ों के अनुभाग से आता है। यह कहता है कि कोई निजी चर नहीं है ... लेकिन डबल अंडरस्कोरिंग चीज सबसे नज़दीक है जिसे आप प्राप्त कर सकते हैं - "चूंकि कक्षा-निजी सदस्यों के लिए वैध उपयोग-मामला है (अर्थात् नामों के नामों से बचने के लिए subclasses द्वारा परिभाषित नामों के साथ), इस तरह के एक तंत्र के लिए सीमित समर्थन है, ... " – mgilson

उत्तर

16

डबल अंडरस्कोर नाम सम्मेलन का उपयोग करने का बिंदु से (गलती से) विधि अधिभावी उपवर्गों को रोकने के लिए है।

यदि आप हैं तो इसे ओवरराइड करने के लिए, किसी ने गंभीर वर्ग डिज़ाइन त्रुटि की है। तुम्हें पता है, अभी भी यह कर सकते हैं अपने वस्तु सिर्फ इसलिए नामकरण से:

def _Foo__method(self): 

जहां और एक और अंडरस्कोर के साथ विधि नाम निर्धारित classname उपसर्ग (इस मामले _Foo साथ उपसर्ग में तो)। एक डबल अंडरस्कोर के साथ विधियों और एट्रिब्यूट नाम बदलने की प्रक्रिया को private name mangling कहा जाता है।

यदि आप एक 'निजी' विधि को परिभाषित करना चाहते हैं जो उप-वर्ग में अभी भी अतिसंवेदनशील है, तो आप आम तौर पर इसके बजाय अंडरस्कोर के साथ नामों को चिपके रहते हैं (def _method(self):)।

इसकी गतिशील प्रकृति के कारण, पाइथन में लगभग कुछ भी वास्तव में निजी नहीं है; थोड़ा आत्मनिरीक्षण के साथ लगभग कुछ भी पहुंचा जा सकता है।

8

एक डबल अंडरस्कोर उपसर्ग नाम मैंगलिंग का आह्वान करता है, यह एक निजी विधि के बराबर नहीं है। यह विशेष रूप से सबक्लास द्वारा ओवरराइड होने से बचने के लिए डिज़ाइन किया गया है (और इस मामले में, विधि का नाम _Foo__method बन जाता है)।

यदि आपके पास कार्यान्वयन विवरण है, तो इसे एक अंडरस्कोर के साथ उपसर्ग करें, यह पाइथन विधियों के लिए सार्वभौमिक रूप से स्वीकार्य संकेत है जिसे बाहरी रूप से उपयोग नहीं किया जाना चाहिए। इसका कोई प्रवर्तन नहीं है, क्योंकि यह पाइथन कार्य करने का तरीका नहीं है।

+0

मुझे पता है कि यह वास्तव में निजी नहीं है, इसलिए मैंने उद्धरण चिह्नों के बीच निजी लिखा है। –

+0

@ एरनेस्टा यह सिर्फ इतना नहीं है कि यह वास्तव में * निजी नहीं है, यह है कि यह किसी भी तरह से समान या तुलनीय नहीं है - यह पूरी तरह से अलग भूमिका निभाता है। –

+0

मैं इस धारणा के तहत था कि 2 अंडरस्कोर "निजी" से शुरू होने वाली विधियों को कॉल करना ठीक था। शायद यह नहीं है। इस मामले में गलत शब्दावली का उपयोग करने के लिए खेद है। –

3

मुझे विश्वास है कि आप की तरह कुछ करना होगा:

class MoreFoo(Foo): 
    def _Foo__method(self): 
     print('41') 
documented रूप

रूप __spam का कोई भी पहचानकर्ता (कम से कम दो प्रमुख अंडरस्कोर, सबसे एक अनुगामी अंडरस्कोर पर) से टेक्स्ट रूप _classname__spam, जहां classname अग्रणी अंडरस्कोर (रों) छीन के साथ वर्तमान वर्ग के नाम है साथ बदल दिया है।

लेकिन मूल वर्ग के डिजाइनरों की राय है कि आप इसे उपवर्गीकरण से ओवरराइड करना मुश्किल हो जाता है के रूप में कुछ इस तरह करने की ज़रूरत नहीं होना चाहिए के थे डबल अंडरस्कोर के पूरे मुद्दे के साथ शुरू करने के लिए है:

नाम मैंगलिंग इंट्राक्लास विधि कॉल को तोड़ने के बिना सबक्लास को ओवरराइड विधियों को देने के लिए सहायक है।

+0

तकनीकी रूप से यह काम करना चाहिए, लेकिन यह पहली जगह में डबल अंडरस्कोर के दुरुपयोग की अधिक गंभीर समस्या का मुखौटा करता है। –

+0

@AndrewGorcester - निश्चित रूप से। मैं यह नहीं कह रहा हूं कि यह एक अच्छा विचार है। – mgilson

+0

धन्यवाद। मैंने मूल वर्ग नहीं लिखा था। मैं बस अपनी विधियों में से एक को ओवरराइड करना चाहता हूं जो दो अंडरस्कोर से शुरू होता है। –