Python が特定の事柄に 2 つのアンダースコアを使用するのはなぜですか?
-
27-09-2019 - |
質問
私は実際のプログラミング言語にはあまり慣れておらず、Python が初めての言語です。私は Linux について少し知識があり、夏の仕事に就くには十分です (私はまだ高校生です)。仕事中は自由時間がたくさんあるので、それを Python の学習に費やしています。
しかし、一つ気になることがあるんです。次のような式がある場合、Python では具体的に何が違うのですか?
x.__add__(y) <==> x+y
x.__getattribute__('foo') <==> x.foo
私はメソッドが何をするのかなどを知っており、それらが何をするのか理解していますが、私の質問は次のとおりです。上記の二重アンダースコアのメソッドは、見た目が単純な同等のメソッドとどのように違うのでしょうか?
追伸、私はプログラミングの歴史について講義を受けるのは嫌いではありません。実際、知っておくと非常に有益だと思います :) これらが主に Python の歴史的な側面である場合は、自由にとりとめのない話を始めてください。
解決
さて、プログラマのための電源が良いので、動作をカスタマイズする方法があるはずです。多くの場合など演算子のオーバーロード(__add__
、__div__
、__ge__
、...)、属性アクセス(__getattribute__
、__getattr__
(これら二つはdifferntている)、__delattr__
、...)のように、事業者のように、通常の構文は1にマッピング:1それぞれの方法に。他の例では、いくつかの点で、それぞれのメソッドを呼び出す必要特別な手順がある - 例えば、オブジェクトが要求された属性を持っていない場合__getattr__
にのみ呼び出され、__getattribute__
は実装されたりはAttributeErrorを提起されていません。そして、そのうちのいくつかは、あなたがオブジェクトシステムの根性にdeeeeepとほとんど必要ありません取得本当に高度なトピックです。それらすべてを習得する必要はありませんので、ちょうどあなたが/必要かを知りたいリファレンスを参照してください。参照、ここといえば、それはのです。
他のヒント
ここではPythonの生みの親があるそれを説明します:
...ではなく、ために新しい構文を考案 クラスメソッドの特別な種類(例えば 初期化子とデストラクタなど)、I これらの機能は、可能性があることを決めました 単にユーザに要求することによって取り扱わ 特別のメソッドを実装します このよう
__init__
、__del__
、およびなどの名前 等々。この命名規則はでした Cここで、識別子から採取 アンダースコアで始まることに予約されています コンパイラによると、多くの場合、特別なを持っています 以下のような意味(例えば、マクロ Cプリプロセッサで__FILE__
)。
...
私もできるようにするには、この技術を使用します 振る舞いを再定義するためのユーザクラス Pythonの演算子の。以前のように 留意、PythonはCで実装されており、 に関数ポインタのテーブルを使用しています の様々な機能を実装 組み込みオブジェクト(例えば、「GET 属性」、 『追加』と 『コール』)。に これらの機能を定義することを可能にします ユーザ定義のクラスで、私がマッピングされました 特別に、様々な関数ポインタ このよう
__getattr__
としてメソッド名、__add__
、および__call__
。 aがあります これらの間の直接の対応 名前と機能のテーブル 1の時に定義することがあるのポインタ 実装する新しいPythonはC言語でオブジェクトます。
あなたは2つのアンダースコア(なし末尾のアンダースコア)でメソッドを起動すると、Pythonの のルールをマングリング名が適用されます。これは緩く、そのようなC ++やJavaなどの他のオブジェクト指向言語からprivate
キーワードをシミュレートする方法です。 (そうであっても、方法はまだJavaとC ++のメソッドがプライベートであることを方法で、技術的にプライベートではありませんが、それは、例えば外部から「で取得するのは難しい」です。)
大手2と2つの末尾のアンダースコアを持つ方法は、「ビルトイン」ことを、彼らはインタプリタによって使用され、一般組み込み機能オーバーロードされた演算子または他の具体的な実装であるしているされた方法、と考えられています。
彼らは、Pythonインタプリタは、特定の状況でそれらを使用するように指定するために使用されます。
例えば、__add__
機能は、カスタムクラスのための仕事に+
演算子を可能にします。追加しようとしたときそうしないと定義されていないエラーのいくつかの並べ替えを取得します。
は歴史的観点から、先頭の下線は、多くの場合、名前が定義するそれらそのパッケージ/モジュール/ライブラリの内部と考えられるべきであることをプログラマに示すための方法として使用されてきました。プライベート名前空間のための良いサポートを提供していない言語では、アンダースコアを使用することをエミュレートするための規則です。あなたは「__foo__」という名前のメソッドを定義するときにPythonでは、メンテナンスプログラマは、特別にどの起こっている何かが「FOO」という名前のメソッドで起きていないことを名前から知っています。 Pythonは、過負荷「+」の内部メソッドとして「追加」を使用することに選びだしていた場合、あなたは多くの混乱を招くことなく、方法「追加」を持つクラスを持つことができませんでした。アンダースコアは、いくつかの魔法が起こるだろうという合図として役立ちます。
現在、他の多くの質問がこの質問の重複としてマークされており、そのうちの少なくとも 2 つは、 __spam__
メソッドが呼び出されるか、規約で何と呼ばれているか、既存の回答のどれもそれをカバーしていないため、次のようになります。
実はどちらにも正式な名前はありません。
多くの開発者は非公式にこれらを「Double UNDERscore」を意味する「ダンダー メソッド」と呼んでいます。
「魔法のメソッド」という用語を使用する人もいますが、それは、ダンダーメソッド、特別なメソッド (下記を参照)、またはその 2 つの中間の何かを意味する間でいくぶん曖昧です。
そこには は 公式用語「特殊属性」。これはダンダー メソッドと完全にではありませんが、密接に重複しています。の データ・モデル このリファレンスの章では、特別な属性とは何かについてまったく説明されていませんが、基本的な考え方は、それが次の少なくとも 1 つであるということです。
- インタプリタ自体またはその組み込みコードによって提供される属性。
__name__
関数について。 - インタプリタ自体によって実装されるプロトコルの一部である属性。
__add__
のために+
オペレーター、または__getitem__
インデックス付けとスライス用。 - インタプリタがインスタンスを無視してクラスに直接アクセスすることにより、特別に検索できる属性。
__add__
また。
ほとんどの特別な属性はメソッドですが、すべてではありません (例: __name__
ではありません)。そして、ほとんどは「ダンダー」規則を使用しますが、すべてではありません(例: next
Python 2.x のイテレータのメソッド)。
一方、ほとんどのダンダー メソッドは特別な属性ですが、すべてではありません。特に、stdlib または外部ライブラリが同じように機能する独自のプロトコルを定義したいことはそれほど珍しいことではありません。 pickle
プロトコル。
[投機] Pythonが影響を受けたのは、 アルゴル68, グイド Algol68 を使用した可能性があります アムステルダム大学 ここで、Algol68 には同様の "ストッピング体制」は「引用の削除」と呼ばれます。Algol68 では、 演算子、型、キーワード できる 別の書体で表示されます (通常は **大胆な**、 または __下線付き__)、ソースコード ファイルでは、この書体は引用符で実現されます。'abs' (' での引用と同様の引用)ウィキテキスト')
Algol68 ⇒ Python (メンバー関数にマッピングされた演算子)
- 「そして」 ⇒ __そして__
- 「または」 ⇒ __または__
- 「ない」 ⇒ ない
- 'エンティア' ⇒ __trunc__
- 'shl' ⇒ __lshift__
- 'shr' ⇒ __rshift__
- 'upb' ⇒ __sizeof__
- '長い' ⇒ __長い__
- 'int' ⇒ __int__
- '実数' ⇒ __float__
- 'フォーマット' ⇒ __format__
- 'repr' ⇒ __repr__
- '腹筋' ⇒ __腹筋__
- 「マイナス」 ⇒ __neg__
- 'マイナス' ⇒ __sub__
- 'プラス' ⇒ __add__
- '回' ⇒ __mul__
- 'mod' ⇒ __mod__
- 'div' ⇒ __truediv__
- 「以上」 ⇒ __div__
- 'アップ' ⇒ __pow__
- 「私」 ⇒ 画像
- 「れ」⇒本物
- 「conj」 ⇒ 共役
Algol68 では、これらは次のように呼ばれていました。 大胆な名前, 、例えば 腹筋, 、ただし、Pythonでは「under-under-abs」__abs__です。
私の2セント:¢ したがって、幽霊のように、Python クラスを切り取って Wiki に貼り付けると、魔法のように Algol68 のクラスが生まれ変わることがあります。 大胆な キーワード。¢