2012-09-20 19 views
12

मुझे पता है कि पाइथन क्लास विशेषताओं/विधियों के लिए डबल अंडरस्कोर का क्या अर्थ है, लेकिन क्या इसका मतलब विधि तर्क के लिए कुछ है?पाइथन विधि के लिए डबल अंडरस्कोर * तर्क *

ऐसा लगता है कि आप विधियों के लिए डबल अंडरस्कोर से शुरू होने वाले तर्क को पारित नहीं कर सकते हैं। यह भ्रमित है क्योंकि आप सामान्य कार्यों के लिए ऐसा कर सकते हैं।

def egg(__a=None): 
    return __a 

print "egg(1) =", 
print egg(1) 
print 


class Spam(object): 

    def egg(self, __a=None): 
     return __a 

print "Spam().egg(__a=1) =", 
print Spam().egg(__a=1) 

इस स्क्रिप्ट पैदावार चल रहा है::

egg(1) = 1 

Spam().egg(__a=1) = 
Traceback (most recent call last): 
    File "/....py", line 15, in <module> 
    print Spam().egg(__a=1) 
TypeError: egg() got an unexpected keyword argument '__a' 

मैं अजगर 2.7.2 के साथ इस जाँच की

इस स्क्रिप्ट पर विचार करें।


कुछ अन्य उदाहरण

यह काम करता है:

def egg(self, __a): 
    return __a 


class Spam(object): 

    egg = egg 

Spam().egg(__a=1) 

यह नहीं करता है:

class Spam(object): 

    def _egg(self, __a=None): 
     return __a 

    def egg(self, a): 
     return self._egg(__a=a) 

Spam().egg(1) 

उत्तर

12

नाम mangling के लिए अग्रणी डबल अंडरस्कोर, regardless of where they occur के साथ सभी पहचानकर्ता पर लागू होता है (दूसरा उस खंड में अंतिम वाक्य):

यह परिवर्तन वाक्य रचनात्मक संदर्भ से स्वतंत्र है जिसमें पहचानकर्ता का उपयोग किया जाता है।

यह कार्यान्वित करने और परिभाषित करने के लिए आसान है, और अधिक संगत। यह बेवकूफ प्रतीत हो सकता है, लेकिन पूरा नाम मैंगलिंग सौदा एक बदसूरत छोटी हैक IMHO है; और आपको वैसे भी नामों/विधियों को छोड़कर किसी भी चीज़ के लिए नामों का उपयोग करने की उम्मीद नहीं है।

Spam().egg(_Spam__a=1), साथ ही Spam().egg(1), काम करता है। लेकिन भले ही आप इसे काम कर सकें, अग्रणी अंडरस्कोर (उनमें से किसी भी संख्या) पैरामीटर नामों में कोई स्थान नहीं है। या किसी भी स्थानीय चर (अपवाद: _) में उस मामले के लिए।

संपादित करें: आपको लगता है कि किसी कोने का मामला कभी नहीं माना गया है। दस्तावेज यहां अपरिचित है, या कार्यान्वयन त्रुटिपूर्ण है। ऐसा लगता है कि कीवर्ड तर्क नाम उलझन में नहीं हैं। बाईटकोड (अजगर 3.2) को देखो:

>>> dis.dis(Spam.egg) 
    3   0 LOAD_FAST    0 (self) 
       3 LOAD_ATTR    0 (_egg) 
       6 LOAD_CONST    1 ('__a') # keyword argument not mangled 
       9 LOAD_FAST    1 (a) 
      12 CALL_FUNCTION   256 
      15 RETURN_VALUE 
>>> dis.dis(Spam._egg) 
    2   0 LOAD_FAST    1 (_Spam__a) # parameter mangled 
       3 RETURN_VALUE 

इस तथ्य यह है कि कीवर्ड तर्क (इस मामले {'__a': 1} में) एक dict गुजर के बराबर हैं में निहित किया जा सकता है जिसका कुंजी या तो घायल नहीं किया जाएगा। लेकिन ईमानदारी से, मैं इसे पहले से ही बदसूरत विशेष मामले में एक बदसूरत कोने का मामला कहूंगा और आगे बढ़ूंगा। यह महत्वपूर्ण नहीं है क्योंकि आपको वैसे भी पहचानकर्ताओं का उपयोग नहीं करना चाहिए।

+0

यदि ऐसा होता है "वे कहाँ पाए जाते हैं की परवाह किए बिना", मैं उम्मीद पिछले उदाहरण (एक मैं जोड़ा) काम करता है। मुझे लगता है मुझे पता है कि यह क्यों नहीं करता है; यह "वर्ग नामस्थान" या ऐसा कुछ होना चाहिए (मुझे नहीं पता कि इसके लिए सही शब्द क्या है), है ना? – tkf

+0

मैं भी इसकी अपेक्षा करता हूं, और मुझे आश्चर्य है। मुझे लगता है कि यह दस्तावेज या कार्यान्वयन में एक दोष है। मैं अपने निष्कर्ष जोड़ने के लिए अभी संपादन कर रहा हूं। – delnan

+0

मैं मानता हूं कि यह सुरुचिपूर्ण पैरामीटर नहीं है, लेकिन जब आपके पास फ़ंक्शन में 'self .__ dict __। अपडेट (kwds)' जैसा कुछ है, लेकिन फ़ंक्शन के व्यवहार को नियंत्रित करना चाहते हैं। एकमात्र वैध तर्क नाम मैं व्यवहार को नियंत्रित करने के बारे में सोच सकता हूं, वह डबल अंडरस्कोर से शुरू होता है। – tkf

3

यह _Spam__a में परिवर्तित हो जाता: एक वर्ग के संदर्भ में

In [20]: class Spam(object): 
    ....:  
    ....:   def egg(self, __a=None): 
    ....:    return __a 
    ....: 

In [21]: Spam.egg.__func__.__code__.co_varnames 
Out[21]: ('self', '_Spam__a') 
1

डबल अंडरस्कोर या Name Mangling एक निजी पहचानकर्ता है। अपने उदाहरण में dir (Spam.egg) आज़माएं और आप देखेंगे कि पैरामीटर __a अब _Spam__egg है।

अब आप उपयोग कर सकते हैं:

Spam().egg(_Spam__a=1) 
संबंधित मुद्दे