फ़ंक्शन के नाम से पहले और बाद में कुछ फ़ंक्शन अंडरस्कोर "__" क्यों हैं?


424

यह "अंडरस्कोरिंग" बहुत कुछ प्रतीत होता है, और मैं सोच रहा था कि क्या पायथन भाषा में यह आवश्यकता थी, या केवल सम्मेलन की बात है?

इसके अलावा, क्या कोई व्यक्ति यह बता सकता है कि कौन से कार्य अंडरस्कोर होते हैं, और क्यों ( __init__उदाहरण के लिए)?


8
@AustinHenley: नाम से पहले और बाद में डबल अंडरस्कोर नहीं । आप नाम से पहले केवल अंडरस्कोर सोच रहे हैं ।



@ मैक नोट ध्यान दें कि यह प्रश्न नाम के पहले और बाद में अंडरस्कोर के बारे में पूछता है , और आपके द्वारा प्रस्तावित डुप्लिकेट लक्ष्य केवल नाम से पहले अंडरस्कोर के बारे में पूछता है । हालाँकि, मैं स्वीकार करता हूं कि वहाँ के कुछ उत्तर इस मामले को भी कवर करते हैं।
जार्ज

जवाबों:


526

से अजगर कोड के लिए स्टाइल गाइड - अजगर पीईपी 8 :

वर्णनात्मक: नामकरण शैलियाँ

प्रमुख या अनुगामी अंडरस्कोर का उपयोग करते हुए निम्नलिखित विशेष रूपों को मान्यता दी जाती है (इन्हें आमतौर पर किसी भी मामले के सम्मेलन के साथ जोड़ा जा सकता है):

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

  • single_trailing_underscore_: पाइथन कीवर्ड के साथ संघर्ष से बचने के लिए सम्मेलन द्वारा उपयोग किया जाता है, जैसे

    Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore: जब क्लास की विशेषता का नामकरण किया जाता है, तो नाम मैनलिंग (कक्षा FooBar के अंदर, __booबन जाता है _FooBar__boo; नीचे देखें;) को आमंत्रित करता है ।

  • __double_leading_and_trailing_underscore__: "जादू" ऑब्जेक्ट्स या विशेषताएँ जो उपयोगकर्ता-नियंत्रित नामस्थानों में रहती हैं। जैसे __init__, __import__या __file__। ऐसे नामों का आविष्कार कभी न करें; केवल उन्हें प्रलेखित के रूप में उपयोग करें।

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


6
रेमंड यह भी बताता है कि आप इस वीडियो में लगभग 34 मिनट से शुरू होने वाले नाम का व्यवहार क्यों करना चाहते हैं: youtube.com/watch?v=HTLu2DFOdTg
johncip

5
तो एकल अग्रणी अंडरस्कोर और एक नाम में डबल अग्रणी अंडरस्कोर के बीच का विकल्प सी ++ और जावा में संरक्षित और निजी के बीच चयन करने जैसा है? _single_leading_underscore को बच्चों द्वारा बदला जा सकता है, लेकिन __double_leading_underscore नहीं कर सकता?
एलेक्स डब्ल्यू

2
__double_leading_underscoreहै अभी भी सार्वजनिक , चर बस एक टकराव से बचने के लिए नाम दिया गया है।
cz

59

अन्य उत्तरदाताओं ने "विशेष" या "जादू" विधियों के लिए नामकरण सम्मेलन के रूप में दोहरे अग्रणी और अनुगामी अंडरस्कोर का वर्णन करने में सही हैं।

जब आप इन तरीकों को सीधे ( [10, 20].__len__()उदाहरण के लिए) कह सकते हैं , तो अंडरस्कोर की उपस्थिति एक संकेत है कि इन तरीकों को अप्रत्यक्ष रूप से ( len([10, 20])उदाहरण के लिए) लागू करने का इरादा है । अधिकांश अजगर ऑपरेटरों के पास एक संबंधित "जादू" विधि है (उदाहरण के लिए, a[x]आह्वान करने का सामान्य तरीका a.__getitem__(x))।



5

वास्तव में जब मैं माता-पिता और बच्चे के वर्ग के नामों के बीच अंतर करने की आवश्यकता होती है तो मैं विधि नामों का उपयोग करता हूं। मैंने कुछ कोड पढ़े हैं, जो अभिभावक-बच्चे वर्ग बनाने के इस तरीके का उपयोग करते हैं। एक उदाहरण के रूप में मैं यह कोड प्रदान कर सकता हूं:

class ThreadableMixin:
   def start_worker(self):
       threading.Thread(target=self.worker).start()

   def worker(self):
      try:
        self._worker()
    except tornado.web.HTTPError, e:
        self.set_status(e.status_code)
    except:
        logging.error("_worker problem", exc_info=True)
        self.set_status(500)
    tornado.ioloop.IOLoop.instance().add_callback(self.async_callback(self.results))

...

और बच्चे के पास एक _वर्क विधि है

class Handler(tornado.web.RequestHandler, ThreadableMixin):
   def _worker(self):
      self.res = self.render_string("template.html",
        title = _("Title"),
        data = self.application.db.query("select ... where object_id=%s", self.object_id)
    )

...


क्या यह डबल अंडरस्कोर उपसर्ग नहीं है?
एएमसी

1

इस सम्मेलन का उपयोग विशेष चर या विधियों (तथाकथित "जादू पद्धति") जैसे __init__और के लिए किया जाता है __len__। ये विधियाँ विशेष वाक्यात्मक विशेषताएँ प्रदान करती हैं या विशेष कार्य करती हैं।

उदाहरण के लिए, __file__पायथन फ़ाइल के स्थान को इंगित करता है, __eq__जब a == bअभिव्यक्ति निष्पादित होती है तो निष्पादित किया जाता है।

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

class A:
    def __init__(self, a):  # use special method '__init__' for initializing
        self.a = a
    def __custom__(self):  # custom special method. you might almost do not use it
        pass

0

अजगर में __ के उपयोग को समझने के लिए एक उदाहरण जोड़ा गया। यहाँ सभी __ की सूची है

https://docs.python.org/3/genindex-all.html#_

कुछ वर्गों की पहचानकर्ता (कीवर्ड के अलावा) के विशेष अर्थ हैं। किसी भी संदर्भ में * नाम का कोई भी उपयोग , जो स्पष्ट रूप से प्रलेखित उपयोग का पालन नहीं करता है, चेतावनी के बिना टूटना के अधीन है

__ का उपयोग करके प्रतिबंध

"""
Identifiers:
-  Contain only (A-z, 0-9, and _ )
-  Start with a lowercase letter or _.
-  Single leading _ :  private
-  Double leading __ :  strong private
-  Start & End  __ : Language defined Special Name of Object/ Method
-  Class names start with an uppercase letter.
-

"""


class BankAccount(object):
    def __init__(self, name, money, password):
        self.name = name            # Public
        self._money = money         # Private : Package Level
        self.__password = password  # Super Private

    def earn_money(self, amount):
        self._money += amount
        print("Salary Received: ", amount, " Updated Balance is: ", self._money)

    def withdraw_money(self, amount):
        self._money -= amount
        print("Money Withdraw: ", amount, " Updated Balance is: ", self._money)

    def show_balance(self):
        print(" Current Balance is: ", self._money)


account = BankAccount("Hitesh", 1000, "PWD")  # Object Initalization

# Method Call
account.earn_money(100)

# Show Balance
print(account.show_balance())

print("PUBLIC ACCESS:", account.name)  # Public Access

# account._money is accessible because it is only hidden by convention
print("PROTECTED ACCESS:", account._money)  # Protected Access

# account.__password will throw error but account._BankAccount__password will not
# because __password is super private
print("PRIVATE ACCESS:", account._BankAccount__password)

# Method Call
account.withdraw_money(200)

# Show Balance
print(account.show_balance())

# account._money is accessible because it is only hidden by convention
print(account._money)  # Protected Access
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.