ทำไมบางฟังก์ชั่นจึงมีขีดล่าง“ __” ก่อนและหลังชื่อฟังก์ชัน?


424

"การเน้น" นี้ดูเหมือนจะเกิดขึ้นมากมายและฉันสงสัยว่านี่เป็นข้อกำหนดในภาษา Python หรือเป็นเพียงเรื่องของการประชุม?

นอกจากนี้คนชื่อและอธิบายฟังก์ชั่นที่มีแนวโน้มที่จะมีขีดล่างและทำไม ( __init__เช่น)?


8
@AustinHenley: ไม่ใช้เครื่องหมายขีดล่างคู่ก่อนและหลังชื่อ คุณกำลังคิดถึงขีดล่างก่อนชื่อ



@MackM โปรดทราบว่าคำถามนี้ถามเกี่ยวกับขีดล่างก่อนและหลังชื่อและเป้าหมายที่ซ้ำกันที่คุณเสนอให้ถามเกี่ยวกับขีดล่างข้างหน้าชื่อเท่านั้น แม้ว่าฉันยอมรับว่ามีคำตอบบางส่วนที่ครอบคลุมกรณีนี้เช่นกัน
Georgy

คำตอบ:


526

จากPython PEP 8 - คู่มือสไตล์สำหรับ Python Code :

อธิบาย: รูปแบบการตั้งชื่อ

รูปแบบพิเศษต่อไปนี้ที่ใช้ขีดเส้นใต้หรือขีดล่างได้รับการยอมรับ (โดยทั่วไปสามารถรวมกับการประชุมกรณีใด ๆ ):

  • _single_leading_underscore: ตัวบ่งชี้ "การใช้ภายใน" อ่อน เช่นfrom M import *ไม่นำเข้าวัตถุที่ชื่อขึ้นต้นด้วยเครื่องหมายขีดล่าง

  • single_trailing_underscore_: ใช้โดยการประชุมเพื่อหลีกเลี่ยงข้อขัดแย้งกับคำหลัก Python เช่น

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

  • __double_leading_underscore: เมื่อตั้งชื่อแอตทริบิวต์ class ให้เรียกใช้ชื่อ mangling (ภายในคลาส FooBar __booกลายเป็น_FooBar__boo; ดูด้านล่าง)

  • __double_leading_and_trailing_underscore__: วัตถุหรือแอตทริบิวต์ "เวทมนต์" ที่อาศัยอยู่ในเนมสเปซที่ผู้ใช้ควบคุม เช่น__init__, หรือ__import__ __file__ไม่เคยประดิษฐ์ชื่อดังกล่าว ใช้เป็นเอกสารเท่านั้น

โปรดทราบว่าชื่อที่มีเครื่องหมายขีดเส้นใต้และขีดเส้นใต้แบบคู่จะถูกสงวนไว้สำหรับ Python เป็นหลัก: "อย่าประดิษฐ์ชื่อดังกล่าวเพียงใช้มันเป็นเอกสาร"


6
เรย์มอนด์ยังอธิบายว่าเพราะเหตุใดคุณจึงต้องการให้ชื่อ mangling พฤติกรรมเริ่มต้นที่ประมาณ 34 นาทีในวิดีโอนี้: youtube.com/watch?v=HTLu2DFOdTg
johncip

5
ทางเลือกระหว่างขีดเส้นใต้นำเดี่ยวและขีดล่างนำสองจุดในชื่อนั้นเป็นบิตเช่นการเลือกระหว่างการป้องกันและส่วนตัวใน C ++ และ Java? เด็กสามารถ _single_leading_underscore สามารถเปลี่ยนแปลงได้ แต่ __double_leading_underscore ไม่สามารถทำได้ใช่ไหม
Alex W

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))

...

และเด็กที่มีวิธี _worker

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)
    )

...


นี่ไม่ใช่คำนำหน้าขีดเส้นใต้คู่หรือไม่
AMC

1

การประชุมนี้จะใช้สำหรับตัวแปรพิเศษหรือวิธีการ (ที่เรียกว่า“วิธีวิเศษ”) เช่นและ__init__ __len__วิธีการเหล่านี้ให้คุณสมบัติทางวากยสัมพันธ์พิเศษหรือทำสิ่งพิเศษ

ตัวอย่างเช่น__file__ระบุตำแหน่งของไฟล์ Python ที่__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

เพิ่มตัวอย่างเพื่อทำความเข้าใจการใช้ __ ใน python นี่คือรายการทั้งหมด __

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.