ऑब्जेक्ट नाम से पहले सिंगल और डबल अंडरस्कोर का अर्थ क्या है?


1288

क्या कोई कृपया पायथन में किसी वस्तु के नाम से पहले अंडरस्कोर होने के सही अर्थ और दोनों के बीच अंतर को स्पष्ट कर सकता है?

इसके अलावा, क्या इसका अर्थ वही है जो प्रश्न में वस्तु चर है, एक फ़ंक्शन, एक विधि, आदि?


2
एक और धागे से एक बड़ा संक्षिप्त जवाब: stackoverflow.com/a/8689983/911945
एंटोन तारासेंको

जवाबों:


1152

सिंगल अंडरस्कोर

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

PEP-8 उद्धृत करने के लिए :

_single_leading_underscore: कमजोर "आंतरिक उपयोग" सूचक। Eg from M import *उन वस्तुओं को आयात नहीं करता है जिनका नाम अंडरस्कोर से शुरू होता है।

डबल अंडरस्कोर (नाम मंगलिंग)

से अजगर डॉक्स :

फॉर्म के किसी भी पहचानकर्ता __spam(कम से कम दो अग्रणी अंडरस्कोर, अधिकांश एक ट्रेलिंग अंडरस्कोर पर) को शाब्दिक रूप से बदल दिया जाता है _classname__spam, जहां classnameवर्तमान अंडरस्कोर (एस) के साथ वर्तमान वर्ग का नाम छीन लिया गया है। यह पैंतरेबाज़ी पहचानकर्ता की वाक्यात्मक स्थिति की परवाह किए बिना की जाती है, इसलिए इसका उपयोग कक्षा-निजी उदाहरण और वर्ग चर, विधियों, ग्लोबल्स में संग्रहीत चर और यहां तक ​​कि चर में संग्रहीत चर को परिभाषित करने के लिए किया जा सकता है। अन्य वर्गों के उदाहरणों पर इस वर्ग के लिए निजी।

और उसी पृष्ठ से एक चेतावनी:

नाम प्रबंधन का उद्देश्य वर्गों को "निजी" उदाहरण चर और विधियों को परिभाषित करने का एक आसान तरीका देना है, बिना व्युत्पन्न वर्गों द्वारा परिभाषित उदाहरण चर के बारे में चिंता किए बिना, या वर्ग के बाहर कोड द्वारा उदाहरण चर के साथ मैकिंग करना। ध्यान दें कि हादसों से बचने के लिए ज्यादातर नियमों को डिजाइन किया गया है; यह अभी भी एक निर्धारित आत्मा के लिए संभव है जो निजी समझे जाने वाले चर को एक्सेस या संशोधित कर सके।

उदाहरण

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

17
क्या होगा यदि 2 अंडरस्कोर के साथ एक चर नाम घोषित किया जाए जो कक्षा में नहीं है? यह सिर्फ एक सामान्य चर है तो सही?
ध्रुव रमणी

5
__एक चर नाम के रूप में बस डबल अंडरस्कोर का अर्थ क्या है ? जैसेa, __ = foo()
AJ

104
यह उत्तर बेहद भ्रामक है, क्योंकि यह पाठक को यह विश्वास दिलाता है कि डंडर्सकोर का उपयोग "सुपरपाइरेस्ट" करने के लिए किया जाता है। यह मामला नहीं है, जैसा कि रेमंड हेटिंगर द्वारा यहां बताया गया है, जो स्पष्ट रूप से कहते हैं कि डंडर्सकोर का उपयोग सदस्यों को निजी रूप से चिह्नित करने के लिए किया जाता है, जबकि इसे निजी के विपरीत डिजाइन किया गया था।
मार्कस मेस्कैन

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

6
@MarkusMeskanen: स्वतंत्रता उपवर्गों के लिए समान नामों का उपयोग करने के लिए है, क्योंकि सुपरक्लास सुपरक्लास को क्लोब किए बिना करता है - दूसरे पासवर्डों में, सुपरक्लास के डंडर नाम स्वयं ही निजी हो जाते हैं।
एथन फुरमान

311

अब तक के उत्कृष्ट जवाब लेकिन कुछ ख़बरें गायब हैं। एक एकल प्रमुख अंडरस्कोर केवल एक कन्वेंशन नहीं है : यदि आप उपयोग करते हैं from foobar import *, और मॉड्यूल foobarएक __all__सूची को परिभाषित नहीं करता है , तो मॉड्यूल से आयात किए गए नामों में एक प्रमुख अंडरस्कोर शामिल नहीं है । मान लीजिए कि यह ज्यादातर एक सम्मेलन है, क्योंकि यह मामला काफी अस्पष्ट है; ;-)

अग्रणी अंडरस्कोर सम्मेलन में व्यापक रूप से प्रयोग किया जाता है न कि केवल के लिए निजी नाम, लेकिन यह भी क्या सी ++ कहेंगे के लिए संरक्षित लोगों - उदाहरण के लिए, तरीकों में से ऐसे नाम हैं जो पूरी तरह से करना है ओवरराइड उपवर्गों (यहां तक कि जो कि द्वारा होने के लिए है के बाद से ओवरराइड करने के लिए आधार वर्ग वे raise NotImplementedError! -) अक्सर एकल-प्रमुख-अंडरस्कोर नाम होते हैं जो उस वर्ग (या उपवर्ग) के उदाहरणों का उपयोग करके कोड को इंगित करते हैं जो कहा जाता है कि विधियों को सीधे बुलाया नहीं जाता है।

उदाहरण के लिए, एफआईएफओ की तुलना में एक अलग कतारबद्ध अनुशासन के साथ एक थ्रेड-सुरक्षित कतार बनाने के लिए, एक क्यू को आयात करता है, क्यूक्वेक् क्यू को उप-वर्ग करता है, और इस तरह के तरीकों को ओवरराइड करता है _getऔर _put; "क्लाइंट कोड" उन ("हुक") तरीकों को कभी नहीं कहता है, बल्कि ("आयोजन") सार्वजनिक विधियों जैसे putऔर get(इसे टेम्पलेट विधि डिज़ाइन पैटर्न के रूप में जाना जाता है - उदाहरण के लिए यहां देखें एक वीडियो पर आधारित एक दिलचस्प प्रस्तुति इस विषय पर मेरी बात, प्रतिलेख के सार के साथ)।

संपादित करें: वार्ता के विवरण में वीडियो लिंक अब टूट गए हैं। आप पहले दो वीडियो यहां और यहां पा सकते हैं ।


1
तो आप यह कैसे तय करते हैं कि इसका उपयोग _var_nameया उपयोग करना है या var_nameनहीं __all__?
एंडोलिथ

3
@endolith अपने कोड के पाठक को संकेत देने के लिए प्रमुख अंडरस्कोर का उपयोग करें कि वे शायद इसका उपयोग न करें (जैसे, क्योंकि आप इसे संस्करण 2.0 में बदल सकते हैं, या यहां तक ​​कि 1.1); __all__जब भी आप मॉड्यूल को from spam import *अनुकूल बनाना चाहते हों, तो स्पष्ट उपयोग करें (इंटरएक्टिव इंटरप्रेटर सहित)। तो ज्यादातर समय, जवाब दोनों है
१५:

@AlexMartelli क्या यह आयात संबंधित नियम कानूनी रूप से डॉक्स या कहीं और पर चर्चा की गई है?
विक्रोबोट

1
मुझे C ++ सादृश्य पसंद है। सबसे पहले, मैं इसे नापसंद करता हूं जब लोग _ निजी फोन करते हैं । जाहिर है कि मैं एनालॉग्स के बारे में बात कर रहा हूं, क्योंकि पायथन में वास्तव में कुछ भी निजी नहीं है । जब अर्थ विज्ञान में गोता मैं कहता हूँ कि हम टाई कर सकते हैं _जावा के लिए संरक्षित के बाद से proctected जावा में अर्थ है "व्युत्पन्न वर्ग और / या एक ही पैकेज में"। PEP8 के बाद से मॉड्यूल के साथ पैकेज को बदलें पहले से ही हमें बताता है कि आयात के _बारे में बात करते समय केवल एक सम्मेलन नहीं है *और वहां आपके पास है। और निश्चित रूप __से जावा के निजी के बराबर होगा जब एक वर्ग के भीतर पहचानकर्ताओं के बारे में बात कर रहे हों।
मारियस मुकेनिकु

2
जबकि एक सभ्य जवाब, यह भी भारी आत्म प्रचार है।
हाइब्रिड वेब देव

298

__foo__: यह सिर्फ एक सम्मेलन है, पायथन सिस्टम के लिए उन नामों का उपयोग करने का एक तरीका है जो उपयोगकर्ता नामों के साथ संघर्ष नहीं करेंगे।

_foo: यह सिर्फ एक कन्वेंशन है, प्रोग्रामर के लिए यह दर्शाने का एक तरीका है कि वैरिएबल निजी है (पाइथन में जो भी मतलब है)।

__foo: इसका वास्तविक अर्थ है: दुभाषिया इस नाम की जगह यह _classname__fooसुनिश्चित करने के तरीके के साथ प्रतिस्थापित करता है कि नाम किसी अन्य वर्ग में समान नाम के साथ ओवरलैप नहीं होगा।

अंडरस्कोर के किसी अन्य रूप का अर्थ पायथन दुनिया में नहीं है।

इन सम्मेलनों में वर्ग, चर, वैश्विक आदि के बीच कोई अंतर नहीं है।


6
बस भर आया __fooऔर उत्सुक था। यह अन्य वर्गों के साथ समान विधि नामों के साथ कैसे ओवरलैप हो सकता है? मेरा मतलब है कि आपको अभी भी इसे एक्सेस करना होगा instance.__foo()(यदि इसे इंटरप्रेटर द्वारा नाम नहीं दिया गया), है ना?
बिभास देबनाथ

81
यह लड़का बताता है कि from module import *अंडरस्कोर-उपसर्गित वस्तुओं को आयात नहीं करता है। इसलिए, _fooकेवल एक सम्मेलन से अधिक है।
dotancohen

4
@ बिभास: यदि वर्ग Bउपवर्गों को Aलागू करता है foo(), और दोनों कार्यान्वित करते हैं , तो विरासत B.foo()में .foo()मिला है A। का एक उदाहरण Bकेवल उपयोग करने में सक्षम होगा B.foo(), को छोड़कर super(B).foo()
naught101

3
के लिए __dunder__नाम, अंतर्निहित आमंत्रण उदाहरण शब्दकोश को छोड़, तो यह कुछ मामलों में सिर्फ एक नामकरण परंपरा से शायद कुछ और जानें (देखें विशेष विधि देखने डेटामॉडल में खंड)।
विम

205

._variable अर्धवार्षिक है और सिर्फ सम्मेलन के लिए है

.__variableअक्सर गलत तरीके से सुपरपाइरेंट माना जाता है, जबकि यह वास्तविक अर्थ है कि आकस्मिक पहुंच को रोकने के लिए केवल नाम मात्र का प्रयोग किया जाए [1]

.__variable__ आम तौर पर बिलिन विधियों या चर के लिए आरक्षित है

.__mangledयदि आप चाहते हैं कि आप अभी भी चर का उपयोग कर सकते हैं। डबल केवल अंडरमेमल्स को नामांकित करता है, या नाम बदल देता है, जैसे कुछ को चरinstance._className__mangled

उदाहरण:

class Test(object):
    def __init__(self):
        self.__a = 'a'
        self._b = 'b'

>>> t = Test()
>>> t._b
'b'

t._b सुलभ है क्योंकि यह केवल सम्मेलन द्वारा छिपा हुआ है

>>> t.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'

t .__ यह नहीं पाया गया है क्योंकि यह अब namemangling के कारण मौजूद नहीं है

>>> t._Test__a
'a'

instance._className__variableकेवल डबल अंडरस्कोर नाम के बजाय एक्सेस करके , आप छिपे हुए मूल्य तक पहुंच सकते हैं


लेकिन कैसे के बारे में अगर "__a" एक वर्ग चर था, तो आप अजगर डॉक्स से निर्देश के साथ भी इसे एक्सेस नहीं कर सकते हैं ..
विटाली टेरज़ीव

कृपया आप अपने उत्तर को विरासत के संबंध में डबल अंडरस्कोर के उदाहरण के साथ अपडेट कर सकते हैं?
चर

115

शुरुआत में सिंगल अंडरस्कोर:

पायथन में असली निजी तरीके नहीं हैं। इसके बजाय, विधि या विशेषता नाम की शुरुआत में एक अंडरस्कोर का मतलब है कि आपको इस विधि तक नहीं पहुंचना चाहिए, क्योंकि यह एपीआई का हिस्सा नहीं है।

class BaseForm(StrAndUnicode):

    def _get_errors(self):
        "Returns an ErrorDict for the data provided for the form"
        if self._errors is None:
            self.full_clean()
        return self._errors

    errors = property(_get_errors)

(यह कोड स्निपेट django स्रोत कोड से लिया गया था: django / forms / forms.py)। इस कोड में, errorsएक सार्वजनिक संपत्ति है, लेकिन जिस विधि से यह संपत्ति कॉल करती है, _get_errors, "निजी" है, इसलिए आपको इसे एक्सेस नहीं करना चाहिए।

शुरुआत में दो अंडरस्कोर:

इससे बहुत भ्रम पैदा होता है। इसका उपयोग निजी पद्धति बनाने के लिए नहीं किया जाना चाहिए। इसका उपयोग आपके तरीके को उपवर्ग द्वारा अधिग्रहित किए जाने या गलती से पहुंचने से बचने के लिए किया जाना चाहिए। आइए एक उदाहरण देखें:

class A(object):
    def __test(self):
        print "I'm a test method in class A"

    def test(self):
        self.__test()

a = A()
a.test()
# a.__test() # This fails with an AttributeError
a._A__test() # Works! We can access the mangled name directly!

आउटपुट:

$ python test.py
I'm test method in class A
I'm test method in class A

अब एक उपवर्ग B बनाएँ और __test विधि के लिए अनुकूलन करें

class B(A):
    def __test(self):
        print "I'm test method in class B"

b = B()
b.test()

आउटपुट होगा…।

$ python test.py
I'm test method in class A

जैसा कि हमने देखा है, A.test () ने B .__ परीक्षण () विधियों को कॉल नहीं किया, जैसा कि हम उम्मीद कर सकते हैं। लेकिन वास्तव में, यह __ के लिए सही व्यवहार है। __Test () नाम की दो विधियाँ स्वतः ही नाम बदलकर (mangled) हो जाती हैं _A__test () और _B__test () के लिए, इसलिए वे गलती से ओवरराइड नहीं करती हैं। जब आप __ से शुरू करने का एक तरीका बनाते हैं तो इसका मतलब है कि आप किसी को भी इसे ओवरराइड करने में सक्षम नहीं होना चाहते हैं, और आप केवल इसे अपनी कक्षा के अंदर से एक्सेस करने का इरादा रखते हैं।

शुरुआत और अंत में दो अंडरस्कोर:

जब हमें कोई विधि दिखाई देती है __this__, तो उसे कॉल न करें। यह एक विधि है जिसे अजगर को बुलाने के लिए है, न कि आप को। चलो एक नज़र डालते हैं:

>>> name = "test string"
>>> name.__len__()
11
>>> len(name)
11

>>> number = 10
>>> number.__add__(40)
50
>>> number + 50
60

हमेशा एक ऑपरेटर या देशी फ़ंक्शन होता है जो इन जादुई तरीकों को कॉल करता है। कभी-कभी यह विशिष्ट स्थितियों में केवल एक हुक अजगर कॉल है। उदाहरण के लिए __init__()कहा जाता है जब वस्तु का निर्माण करने के बाद __new__()कहा जाता है उदाहरण के निर्माण के लिए ...

चलिए एक उदाहरण लेते हैं ...

class FalseCalculator(object):

    def __init__(self, number):
        self.number = number

    def __add__(self, number):
        return self.number - number

    def __sub__(self, number):
        return self.number + number

number = FalseCalculator(20)
print number + 10      # 10
print number - 20      # 40

अधिक जानकारी के लिए, PEP-8 मार्गदर्शिका देखें । अधिक जादुई तरीकों के लिए, इस पीडीएफ को देखें ।


1
इस उत्तर को स्वयं संपादित करने के बाद, मैं stackoverflow.com/a/8689983/1048186
JosiahYoder- निष्क्रिय को छोड़कर

आपको क्या मतलब है "जैसा कि हमने देखा है, A.test () ने B .__ परीक्षण () विधियों" को कॉल नहीं किया है - आपने A.test () को कहां बुलाया है?
चर

18

कभी-कभी आपके पास क्या होता है जैसा कि एक प्रमुख अंडरस्कोर के साथ एक टपल दिखाई देता है

def foo(bar):
    return _('my_' + bar)

इस मामले में, क्या चल रहा है कि _ () स्थानीयकरण फ़ंक्शन के लिए एक उपनाम है जो पाठ पर संचालित होता है, जो इसे स्थानीय भाषा पर आधारित है, आदि। उदाहरण के लिए, स्फिंक्स ऐसा करता है, और आप आयातों के बीच पाएंगे

from sphinx.locale import l_, _

और sphinx.locale में _ () को कुछ स्थानीयकरण फ़ंक्शन के उपनाम के रूप में सौंपा गया है।


10

चूँकि इतने सारे लोग रेमंड की बात का जिक्र कर रहे हैं , मैं बस यह लिख कर थोड़ा आसान कर दूंगा कि उसने क्या कहा:

डबल अंडरस्कोर का इरादा गोपनीयता के बारे में नहीं था। आशय यह था कि इसे ठीक इसी तरह इस्तेमाल किया जाए

class Circle(object):

    def __init__(self, radius):
        self.radius = radius

    def area(self):
        p = self.__perimeter()
        r = p / math.pi / 2.0
        return math.pi * r ** 2.0

    def perimeter(self):
        return 2.0 * math.pi * self.radius

    __perimeter = perimeter  # local reference


class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

यह वास्तव में गोपनीयता के विपरीत है, यह सब स्वतंत्रता के बारे में है। यह आपके उपवर्गों को दूसरों को तोड़े बिना किसी एक विधि को ओवरराइड करने के लिए स्वतंत्र बनाता है

आप की एक स्थानीय संदर्भ नहीं रखते कहो perimeterमें Circle। अब, एक व्युत्पन्न वर्ग स्पर्श किए बिना, Tireके कार्यान्वयन को ओवरराइड करता है । जब आप कॉल करते हैं , तो सिद्धांत रूप में यह अभी भी गणना के लिए उपयोग किया जाना चाहिए , लेकिन वास्तव में यह उपयोग कर रहा है , जो कि इच्छित व्यवहार नहीं है। इसलिए हमें सर्किल में स्थानीय संदर्भ की आवश्यकता है।perimeterareaTire(5).area()Circle.perimeterTire.perimeter

लेकिन __perimeterइसके बजाय क्यों _perimeter? क्योंकि _perimeterअभी भी व्युत्पन्न वर्ग को ओवरराइड करने का मौका देता है:

class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

    _perimeter = perimeter

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

यदि आपकी कक्षा विरासत में नहीं मिलेगी, या विधि ओवरराइडिंग कुछ भी नहीं तोड़ती है, तो आपको बस ज़रूरत नहीं है __double_leading_underscore


धन्यवाद, स्लाइड ने ठीक से प्रदर्शित नहीं किया, इसलिए मैंने इस बात को समाप्त नहीं किया कि मेरा कोड विफल क्यों होगा।
cgte

8

यदि कोई वास्तव में एक चर-केवल पढ़ने के लिए करना चाहता है, तो IMHO सबसे अच्छा तरीका संपत्ति () का उपयोग करना होगा, जिसके पास केवल प्राप्तकर्ता है। संपत्ति () के साथ हम डेटा पर पूरा नियंत्रण रख सकते हैं।

class PrivateVarC(object):

    def get_x(self):
        pass

    def set_x(self, val):
        pass

    rwvar = property(get_p, set_p)  

    ronly = property(get_p) 

मैं समझता हूं कि ओपी ने थोड़ा अलग सवाल पूछा था, लेकिन जब से मुझे एक और सवाल मिला कि 'निजी चर कैसे सेट करें' इस एक के साथ डुप्लिकेट चिह्नित है, तो मैंने इस अतिरिक्त जानकारी को यहां जोड़ने का सोचा।


6

करने के लिए accroding https://dbader.org/blog/meaning-of-underscores-in-python

  • सिंगल लीडिंग अंडरस्कोर (_वर) : एक नाम का नामकरण सम्मेलन आंतरिक उपयोग के लिए है। आमतौर पर पायथन दुभाषिया (वाइल्डकार्ड आयात को छोड़कर) द्वारा लागू नहीं किया गया था और इसका मतलब केवल प्रोग्रामर के संकेत के रूप में था।
  • सिंगल ट्रेलिंग अंडरस्कोर (var_) : पाइथन कीवर्ड के साथ नामकरण संघर्ष से बचने के लिए सम्मेलन द्वारा उपयोग किया जाता है।
  • डबल लीडिंग अंडरस्कोर (__ var) : एक वर्ग के संदर्भ में उपयोग किए जाने पर ट्रिगर का नामकरण। पायथन दुभाषिया द्वारा लागू किया गया।
  • डबल लीडिंग और ट्रेलिंग अंडरस्कोर (__ var__) : पायथन भाषा द्वारा परिभाषित विशेष विधियों को इंगित करता है। अपनी खुद की विशेषताओं के लिए इस नामकरण योजना से बचें।
  • सिंगल अंडरस्कोर (_) : कभी-कभी अस्थायी या महत्वहीन चर के लिए एक नाम के रूप में उपयोग किया जाता है ("परवाह नहीं")। इसके अलावा: पायथन आरईपीएल में अंतिम अभिव्यक्ति का परिणाम।

4

एकल प्रमुख अंडरस्कोर एक सम्मेलन है। यदि किसी एकल अंडरस्कोर के साथ नाम शुरू होते हैं या नहीं, तो दुभाषिया के दृष्टिकोण से कोई अंतर नहीं है।

डबल प्रमुख और अनुगामी अंडरस्कोर के लिए उपयोग किया जाता है में निर्मित जैसे तरीकों, __init__, __bool__, आदि

डबल अग्रणी अंडरस्कोर डब्ल्यू / ओ अनुगामी समकक्षों का एक सम्मेलन भी है, हालांकि, वर्ग विधियों को दुभाषिया द्वारा मंगवाया जाएगा । चर या मूल फ़ंक्शन नाम के लिए कोई अंतर मौजूद नहीं है।


4

महान उत्तर और सभी सही हैं। मैंने सरल परिभाषा / अर्थ सहित सरल उदाहरण प्रदान किया है।

अर्थ:

some_variable - anyone यह सार्वजनिक है कोई भी इसे देख सकता है।

_some_variable - anyone यह सार्वजनिक है कोई भी इसे देख सकता है, लेकिन यह निजी इंगित करने के लिए एक सम्मेलन है ... चेतावनी पाइथन द्वारा कोई प्रवर्तन नहीं किया जाता है।

__some_varaible - s पायथन वेरिएबल नाम की जगह _classname__some_varaible (AKA नाम प्रबंध) करता है और यह दृश्यता को कम / छुपा देता है और निजी चर की तरह अधिक होता है।

बस यहां ईमानदार होना अजगर के प्रलेखन के अनुसार

"" निजी "उदाहरण चर जिसे किसी वस्तु के अंदर से छोड़कर नहीं पहुँचा जा सकता है, अजगर में मौजूद नहीं है"

उदाहरण:

class A():
    here="abc"
    _here="_abc"
    __here="__abc"


aObject=A()
print(aObject.here) 
print(aObject._here)
# now if we try to print __here then it will fail because it's not public variable 
#print(aObject.__here)

_ _some_varaible - .... और यह दृश्यता को कम / छिपा देता है और निजी चर की तरह अधिक होता है। नहीं, नाम मैनलिंग बिंदु है, यह विधि को छिपाता नहीं है।
एएमसी

3

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

लेकिन उदाहरण के लिए, __double_underscore नाम मॉड्यूल में नाम-आधारित नहीं हैं। ऐसा होता है कि एक (या अधिक) अंडरस्कोर से शुरू होने वाले नाम आयात नहीं किए जाते हैं यदि आप सभी मॉड्यूल (मॉड्यूल आयात *) से आयात करते हैं, और न ही मदद (मॉड्यूल) में दिखाए गए नाम हैं।


1
इसके अलावा, एक या अधिक अंडरस्कोर के साथ शुरू होने वाले नाम दो या दो से अधिक ट्रेलिंग अंडरस्कोर हैं जो किसी अन्य नाम के रूप में फिर से व्यवहार करते हैं।
बेंटले 4

3

यहाँ एक सरल उदाहरण है कि कैसे डबल अंडरस्कोर गुण एक विरासत वाले वर्ग को प्रभावित कर सकते हैं। तो निम्न सेटअप के साथ:

class parent(object):
    __default = "parent"
    def __init__(self, name=None):
        self.default = name or self.__default

    @property
    def default(self):
        return self.__default

    @default.setter
    def default(self, value):
        self.__default = value


class child(parent):
    __default = "child"

यदि आप फिर अजगर रेपीएल में एक बच्चे का उदाहरण बनाते हैं, तो आप नीचे देखेंगे

child_a = child()
child_a.default            # 'parent'
child_a._child__default    # 'child'
child_a._parent__default   # 'parent'

child_b = child("orphan")
## this will show 
child_b.default            # 'orphan'
child_a._child__default    # 'child'
child_a._parent__default   # 'orphan'

यह कुछ के लिए स्पष्ट हो सकता है, लेकिन इसने मुझे और अधिक जटिल वातावरण में गार्ड से पकड़ लिया


3

"निजी" उदाहरण चर, जिसे किसी वस्तु के अंदर से छोड़कर नहीं पहुँचा जा सकता है, पायथन में मौजूद नहीं है। हालाँकि, एक सम्मेलन है जो अधिकांश पायथन कोड के बाद होता है: एक अंडरस्कोर (जैसे _spam) के साथ उपसर्गित एक नाम एपीआई के गैर-सार्वजनिक भाग के रूप में माना जाना चाहिए (चाहे वह एक फ़ंक्शन, एक विधि या डेटा सदस्य हो) । इसे बिना किसी नोटिस के कार्यान्वयन का विवरण और परिवर्तन के अधीन माना जाना चाहिए।

संदर्भ https://docs.python.org/2/tutorial/classes.html#pStreet-variables-and-class-local-references


1
_ उदाहरण के लिए c # में आंतरिक तो निजी के लिए बहुत अधिक समान है। डबल अंडरस्कोर यह बहुत अधिक निजी के समान है तो अंडरस्कोर निजी है जो मैं कहूंगा।
ini

2

_ और __ के तथ्य प्राप्त करना बहुत आसान है; अन्य उत्तर उन्हें बहुत अच्छी तरह से व्यक्त करते हैं। उपयोग निर्धारित करने के लिए बहुत कठिन है।

यह है जैसे मैं इसे देखता हूँ:

_

यह इंगित करने के लिए उपयोग किया जाना चाहिए कि एक फ़ंक्शन उदाहरण के लिए एक एपीआई के रूप में सार्वजनिक उपयोग के लिए नहीं है। यह और आयात प्रतिबंध इसे internal# # की तरह व्यवहार करता है ।

__

वंशानुक्रम पदानुक्रम में नाम टकराव से बचने और लेटबाइंडिंग से बचने के लिए उपयोग किया जाना चाहिए। सी # में निजी की तरह।

==>

यदि आप यह इंगित करना चाहते हैं कि कुछ सार्वजनिक उपयोग के लिए नहीं है, लेकिन इसे protectedउपयोग की तरह कार्य करना चाहिए _। यदि आप यह इंगित करना चाहते हैं कि कुछ सार्वजनिक उपयोग के लिए नहीं है, लेकिन इसे privateउपयोग की तरह कार्य करना चाहिए __

यह भी एक उद्धरण है जो मुझे बहुत पसंद है:

समस्या यह है कि एक वर्ग का लेखक वैध रूप से सोच सकता है कि "यह विशेषता / विधि का नाम निजी होना चाहिए, केवल इस वर्ग की परिभाषा के भीतर से ही सुलभ होना चाहिए" और __पीयर सम्मेलन का उपयोग करें। लेकिन बाद में, उस वर्ग का एक उपयोगकर्ता एक उपवर्ग बना सकता है जिसे वैध रूप से उस नाम तक पहुंच की आवश्यकता होती है। इसलिए या तो सुपरक्लास को संशोधित किया जाना चाहिए (जो मुश्किल या असंभव हो सकता है), या उपवर्ग कोड को मैन्युअल रूप से मैंग्ड नाम (जो कि बदसूरत और सबसे अच्छा नाजुक है) का उपयोग करना होगा।

लेकिन मेरे साथ समस्या यह है कि अगर कोई आईडीई नहीं है जो आपको तरीकों से आगे निकल जाने पर चेतावनी देता है, तो त्रुटि को खोजने में आपको थोड़ी देर लग सकती है यदि आपने बेस-क्लास से किसी विधि को गलत तरीके से ओवरराइड किया हो।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.