一部の関数には、関数名の前後にアンダースコア「__」があるのはなぜですか?


424

この「アンダースコア」は頻繁に発生するようですが、これがPython言語での要件なのか、それとも単なる慣習の問題なのかと思いました。

また、誰かが下線を付ける傾向のある関数に名前を付けて説明できますか、そしてその理由は__init__何ですか(たとえば)?


8
@AustinHenley:ないの前に二重のアンダースコア以降の名前。あなたは名前のにだけアンダースコアを考えています。



@MackMこの質問では、名前の前後にアンダースコアが付いていることに注意してください。提案した重複ターゲットは、名前のにのみアンダースコアが付いていることを確認します。しかし、私はそこにある回答のいくつかがこのケースもカバーしていることを認めます。
ジョージー

回答:


526

Python PEP 8から-Pythonコードのスタイルガイド

説明:命名スタイル

先頭または末尾にアンダースコアを使用する次の特殊な形式が認識されます(これらは通常、大文字と小文字の規則と組み合わせることができます)。

  • _single_leading_underscore:弱い「内部使用」インジケータ。たとえばfrom M import *、名前がアンダースコアで始まるオブジェクトはインポートされません。

  • single_trailing_underscore_:慣例により、Pythonキーワードとの競合を回避するために使用されます。

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

  • __double_leading_underscore:クラス属性に名前を付けるときに、名前のマングリングを呼び出します(クラスFooBar内で、に__booなり_FooBar__booます。以下を参照)。

  • __double_leading_and_trailing_underscore__:ユーザー制御の名前空間に存在する「魔法の」オブジェクトまたは属性。たとえば__init____import__または__file__。そのような名前を発明しないでください。文書化されているとおりにのみ使用してください。

アンダースコアとダブルアンダースコアが二重になっている名前は、基本的にPython自体のために予約されていることに注意してください。


6
レイモンドはまた、このビデオに約34分から始まる名前のマングリング動作が必要な理由を説明しています:youtube.com/watch
v

5
名前のシングルリーディングアンダースコアとダブルリーディングアンダースコアの選択は、C ++とJavaでプロテクトとプライベートのどちらを選択するのと少し似ていますか?_single_leading_underscoreは子供が変更できますが、__ double_leading_underscoreは変更できませんか?
Alex W

2
__double_leading_underscoreまだpublicであり、衝突を避けるために変数の名前が変更されるだけです。
cz

59

他の回答者は、「特別な」または「魔法の」メソッドの命名規則として、先頭と末尾の二重のアンダースコアを正しく説明しています。

これらのメソッドを直接([10, 20].__len__()たとえば)呼び出すことができますが、アンダースコアの存在は、これらのメソッドが間接的に(len([10, 20])たとえば)呼び出されることを意図していることのヒントです。ほとんどのPythonオペレーターには、関連する「マジック」メソッドがあります(たとえば、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.