web-dev-qa-db-ja.com

pythonが特定の事柄に2つのアンダースコアを使用するのはなぜですか?

私は実際のプログラミング言語にかなり慣れていないので、Pythonが最初の言語です。Linuxの使い方を少し知っています。夏の仕事に十分なほど十分です(私はまだ高いです)学校)、そして仕事で、私はPythonを学ぶために使用している多くの自由な時間があります。

でも、一つは私を困らせています。 Pythonの正確な違いは、

x.__add__(y) <==> x+y
x.__getattribute__('foo') <==> x.foo

私はメソッドが何を行うか知っています、そして私はそれらが何をするかを取得します、しかし私の質問は次のとおりです:上記の二重下線メソッドは単純な見た目の同等物とどう違うのですか?

追伸、私はプログラミングの歴史について講義を受けても構わないと思います。実際、知っておくととても役に立ちます:)これらが主にPythonの歴史的側面である場合は、自由に取り掛かってください。

51
Andrew

まあ、プログラマーのためのパワーは良いので、振る舞いをカスタマイズする方法があるはずです。演算子のオーバーロード(__add____div____ge__、...)、属性アクセス(__getattribute____getattr__(2つは異なります)、__delattr__、...)など。多くの場合、演算子のように、通常の構文はそれぞれのメソッドに1:1でマッピングされます。他の場合では、ある時点で、それぞれのメソッドの呼び出しを含む特別な手順があります。たとえば、__getattr__は、オブジェクトに要求された属性がなく、__getattribute__は実装されていないか、AttributeErrorが発生します。そして、それらのいくつかは、オブジェクトシステムの根性を理解するための非常に高度なトピックであり、ほとんど必要ありません。ですから、すべてを学ぶ必要はありません。知りたいときや知りたいときにリファレンスを参照してください。参考までに言えば、 ここにあります です。

7
user395760

ここにPython それを説明する の作成者があります:

...特別な種類のクラスメソッド(イニシャライザやデストラクタなど)の新しい構文を考案するのではなく、__init__などの特別な名前のメソッドを実装するようユーザーに要求するだけでこれらの機能を処理できると判断しました__del__など。この命名規則はCから取られたもので、アンダースコアで始まる識別子はコンパイラによって予約されており、特別な意味を持つことがよくあります(たとえば、Cプリプロセッサの__FILE__などのマクロ)。

...

また、この手法を使用して、ユーザークラスがPythonの演算子の動作を再定義できるようにしました。前述のように、PythonはCで実装されており、関数ポインターのテーブルを使用して、組み込みオブジェクトのさまざまな機能を実装します(たとえば、「属性の取得」、「追加」、「呼び出し」)。これらの機能をユーザー定義クラスで定義できるようにするために、さまざまな関数ポインターを__getattr____add____call__などの特別なメソッド名にマップしました。これらの名前と、Cで新しいPythonオブジェクトを実装するときに定義する必要がある関数ポインタのテーブル。

29

2つのアンダースコア(末尾のアンダースコアなし)でメソッドを開始すると、Pythonの name mangling ルールが適用されます。これは、他のOO C++やJavaなどの言語からのprivateキーワードを大まかにシミュレートする方法です(ただし、この方法でも、技術的には非公開ではありません= JavaおよびC++メソッドはプライベートですが、インスタンスの外部から「取得するのが困難」です。)

2つの先行アンダースコアと2つの後続アンダースコアを持つメソッドは、「組み込み」メソッドと見なされます。つまり、これらのメソッドはインタープリターによって使用され、通常、オーバーロードされた演算子またはその他の組み込み機能の具体的な実装です。

16
mipadi

これらは、Pythonインタープリターが特定の状況でそれらを使用する必要があることを指定するために使用されます。

たとえば、__add__関数を使用すると、+演算子でカスタムクラスを処理できます。そうしないと、追加しようとすると、なんらかの定義されていないエラーが発生します。

4
Paul Nathan

歴史的な観点から、先頭のアンダースコアは、名前をそれらを定義するパッケージ/モジュール/ライブラリの内部と見なすべきであることをプログラマーに示す方法としてしばしば使用されてきました。プライベート名前空間を適切にサポートしていない言語では、アンダースコアを使用することでこれをエミュレートできます。 Pythonでは、「__ foo__」という名前のメソッドを定義すると、メンテナンスプログラマは、「foo」という名前のメソッドでは発生していない特別なことが起こっていることを名前から知っています。 Pythonが '+'をオーバーロードするための内部メソッドとして 'add'を使用することを選択した場合、多くの混乱を引き起こさずに 'add'メソッドを持つクラスを持つことはできません。下線はいくつかの魔法が発生する手がかり。

3
William Pursell

他のいくつかの質問がこの質問の重複としてマークされ、少なくとも2つは__spam__メソッドが呼び出されるか、または規則が呼び出されるかを尋ね、既存の回答のどれもそれをカバーしないので、 :

実際には正式な名前もありません。

多くの開発者は、「ダブルアンダースコア」を非公式に「dunderメソッド」と呼んでいます。

一部の人々は「魔法の方法」という用語を使用しますが、意味のあるdunderメソッド、特別なメソッド(以下を参照)、またはこの2つの間のどこかの間は少しあいまいです。


そこにis公式用語「特殊属性」があり、dunderメソッドとは完全にではなく密接に重複しています。リファレンスの Data Model の章では、特別な属性が何であるかを完全に説明していませんが、基本的な考え方は、次の少なくとも1つであるということです。

  • 関数の__name__など、インタープリター自体またはその組み込みコードによって提供される属性。
  • __add__演算子の場合は+、インデックス作成とスライスの場合は__getitem__のように、インタプリタ自体が実装するプロトコルの一部である属性。
  • __add__のように、インスタンスを無視してクラスに直接アクセスすることにより、インタプリタが特別に検索できる属性。

ほとんどの特別な属性はメソッドですが、すべてではありません(たとえば、__name__はそうではありません)。そして、ほとんどが「dunder」規則を使用していますが、すべてではありません(たとえば、Python 2.xのイテレータのnextメソッド)。

一方、ほとんどのdunderメソッドは特別な属性ですが、すべてではありません。特に、stdlibまたは外部ライブラリが pickle プロトコルのように同じように機能する独自のプロトコルを定義することは珍しくありません。

1
abarnert

[推測]Pythonは ALGOL68 の影響を受けました Guido でALGOL68を使用した可能性があります アムステルダム大学 ここで、ALGOL68には同様の「 ストロピングレジーム 」と呼ばれる「引用ストロピング」があります。ALGOL68では、演算子、タイプ、およびキーワードcanは別の書体で表示されます(通常**bold* *、または__ underlined__)、ソースコードファイルでは、この書体は引用符で囲みます。たとえば、 'abs'( ' wikitext 'での引用と同様の引用)

ALGOL68⇒Python(メンバー関数にマッピングされた演算子)

  • 「and」⇒__and__
  • 「または」⇒__or__
  • 「しない」⇒しない
  • 「より大きな」⇒__trunc__
  • 'shl'⇒__lshift__
  • 'shr'⇒__rshift__
  • 'upb'⇒__sizeof__
  • 「長い」⇒__long__
  • 'int'⇒__int__
  • 「実数」⇒__float__
  • 'フォーマット'⇒__format__
  • 'repr'⇒__repr__
  • 'abs'⇒__abs__
  • 「マイナス」⇒__neg__
  • 「マイナス」⇒__sub__
  • 「プラス」⇒__add__
  • '回'⇒__mul__
  • 'mod'⇒__mod__
  • 'div'⇒__truediv__
  • 「オーバー」⇒__div__
  • 「上」⇒__pow__
  • 「im」⇒imag
  • 're'⇒リアル
  • 'conj'⇒共役

ALGOL68では、これらは太字の名前と呼ばれていました。 absですが、Pythonでは "under-under-abs" __abs__です。

私の2セント:¢時々—ゴーストのように— pythonクラスをWikiに貼り付けると、魔法のようにALGOL68のboldキーワード。

0
NevilleDNZ