함수 이름 앞뒤에 일부 함수에 밑줄 "__"이있는 이유는 무엇입니까?


424

이 "언더 스코어링"은 많이 발생하는 것으로 보이며 이것이 파이썬 언어의 요구 사항인지 아니면 단지 관습의 문제인지 궁금합니다.

또한 누군가 어떤 기능에 밑줄이 있고 왜 그런지 설명 할 수 __init__있습니까 (예를 들어)?


8
@AustinHenley : 이름 앞뒤 에 이중 밑줄이 없습니다 . 당신은 전적으로 밑줄 생각 하기 전에 이름.



이 질문은 밑줄에 대해 묻는 @MackM 주 전후에 이름, 당신이 제안하는 중복 대상은 밑줄에 대한 요청 하기 전에 이름. 그러나 나는 거기에 대한 답변 중 일부 가이 경우에도 해당한다는 것을 인정합니다.
조지

답변:


526

로부터 파이썬 코드에 대한 스타일 가이드 - 파이썬 PEP 8 :

설명 : 이름 지정 스타일

선행 또는 후행 밑줄을 사용하는 다음 특수 양식이 인식됩니다 (이는 일반적으로 모든 경우 규칙과 결합 될 수 있음).

  • _single_leading_underscore: 약한 "내부 사용"표시기. 예를 들어 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__. 그런 이름을 발명하지 마십시오. 문서화 된 대로만 사용하십시오.

이중 선행 및 후행 밑줄이있는 이름은 기본적으로 Python 자체에 예약되어 있습니다. "해당 이름을 발명하지 말고 문서화 된 대로만 사용하십시오".


6
Raymond는 또한이 비디오에서 약 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__and와 같은 특수 변수 또는 방법 (소위 "마법 방법")에 사용됩니다 __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

파이썬에서 __의 사용을 이해하는 예제를 추가했습니다. 다음은 All __의 목록입니다.

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.