この記事では、python に関する関連知識を提供します。主に「__missing__()」関数の関連問題を紹介します。皆さんのお役に立つことを願って、この魔法の関数を一緒に見てみましょう。
#
dd = {'name':'PythonCat'} dd.get('age') # 结果:None dd.get('age', 18) # 结果:18 dd['age'] # 报错 KeyError dd.__getitem__('age') # 等同于 dd['age']
get() メソッドの場合、戻り値があり、2 番目のパラメータを取得できます。キーが存在しない場合は戻り内容として渡されるため、許容されます。ただし、他の 2 つの書き込み方法ではエラーが報告されます。
後者の 2 つの記述方法の問題を解決するには、__missing__() マジック メソッドを使用できます。
ここで、次のようなリクエストがあるとします。辞書から特定のキーに対応する値を取得し、値があればその値を返し、値がなければキーを挿入し、それにデフォルト値 (空のリストなど)。
ネイティブ dict を使用する場合、実装は簡単ではありませんが、Python には非常に使いやすい拡張クラス
collections.defaultdict:
図に示すように、存在しないキーを取得する場合、KeyError は再度報告されませんが、デフォルトで辞書に格納されます。
defaultdict でこれができるのはなぜですか?
その理由は、defaultdict は組み込み型 dict を継承した後に __missing__() メソッドも定義しているためです。__getitem__ が存在しない値を受け取ると、入力パラメーターで渡されたファクトリ関数が呼び出されます。上の例では list() を呼び出して空のリストを作成します)。
最も典型的な例として、defaultdict はドキュメントのコメントに次のように記述します。
つまり、
__missing__() のメイン関数は次によって呼び出されます。 KeyError を避けるためにキーが欠落している場合は __getitem__ を使用します。もう 1 つの典型的な使用例は
collections.Counter で、これも dict のサブクラスです。カウントされていないキーをフェッチすると、カウント 0 が返されます。
2. とらえどころのない __missing__()
これは、組み込み型の必須属性ではなく、辞書基本クラスで事前定義されていないためです。
属性値を dict 型から直接取得すると、属性が存在しないことが報告されます:
AttributeError: type object 'object' has noattribute '__missing__'。 dir() を使用して、この属性が存在しないことを確認します。
オブジェクトである dict の親クラスから確認すると、同じ結果が得られます。 ######どうしたの? dict と object の両方に __missing__ 属性がないのはなぜですか?
ただし、最新の公式ドキュメントを確認すると、オブジェクトには明らかに次の属性が含まれています:
出典: https://docs.python.org/3/ リファレンス/datamodel.html?highlight=__missing__#object.__missing__言い換えると、理論的には __missing__ はオブジェクト クラスで事前定義されており、そのドキュメントはこれを証明していますが、実際には定義されていません。書類と現実には齟齬がある!
このように、dict のサブクラス (defaultdict や Counter など) が __missing__ を定義している場合、このマジック メソッドは実際にはそのサブクラスにのみ属する、つまり
Magic で生まれたメソッドです。サブクラスのメソッド!これに基づいて、私は未熟な推測を持っています: __getitem__() は、現在のオブジェクトが dict のサブクラスであるかどうか、および __missing__() があるかどうかを判断してから、それを呼び出します (このメソッドもは親クラスに存在するため、最初に判断されず、直接呼び出されます)。 私はコミュニケーション グループでこの推測について言及しましたが、一部の学生はすぐに CPython ソース コードで検証を見つけました:
そしてこれは興味深いものです。 組み込み型のサブクラスにのみ存在するマジック メソッド。 Python の世界全体を見渡しても、おそらく 2 番目の例を見つけるのは難しいでしょう。
ふと思ったのですが、このとらえどころのない __missing__() は、「人を生き物に変える」のが得意な魔術師のようです。まず、観客に外のガラス越しに彼を見てもらいます(つまり、役人)ただし、ドアが開いたとき、彼は中にいません (つまり、組み込み型)。小道具を変更すると、再び元の状態で表示されます (つまり、dict のサブクラス)。
__missing__() の魔法は、「魔法」そのものに加えて、強力な「魔法」「才能主導」も必要であるということです。
前回の記事で、ネイティブ マジック メソッドが互いに独立していることがわかりました。C 言語インターフェイスでは同じコア ロジックを持つ可能性がありますが、Python 言語インターフェイスでは呼び出し関係がありません。
マジック メソッドのこの種の「通信なし」動作は、一般的なコード再利用原則に違反しており、また、組み込み型のサブクラスでいくつかの奇妙な動作を引き起こします。
公式 Python は、マジック メソッドを再利用するよりも、新しい UserString、UserList、および UserDict サブクラスを提供することを希望します。唯一の合理的な説明は、マジック メソッドを相互に呼び出すコストが高すぎるということのようです。
ただし、特殊なケース __missing__() の場合、Python は妥協し、この代償を支払わなければなりません。
__missing__() は、マジック メソッドの「第二級市民 」です。独立した呼び出し入り口がなく、__getitem__()、つまり __missing__() によって受動的に呼び出すことしかできません。 __getitem__() に依存します。
__init__()、__enter__()、__len__()、__eq__() などの「第一級国民 」とは異なり、オブジェクトの寿命に属します。サイクルまたは実行 プロセス内の特定のノードがトリガーされるか、組み込み関数または演算子によってトリガーされます。これらは比較的独立したイベントであり、依存関係はありません。
__missing__() はメソッド呼び出しを実現するために __getitem__() に依存し、完全な機能を実現するために __getitem__() も __missing__() に依存します。
これを実現するために、__getitem__() はインタープリター コードでバックドアを開き、C 言語インターフェイスから Python インターフェイスに戻り、「__missing__」という名前の特定のメソッドを呼び出します。
そして、これが本当の「魔法」です。今のところ、このような扱いが受けられる魔法のメソッドは __missing__() だけのようです。
Python の辞書には、値を取得するための 2 つの組み込みメソッド、つまり __getitem__() と get() が用意されています。値が存在しない場合、それらの処理戦略は異なります。 ##前者はエラー KeyError を報告し、後者は None を返します。
KeyError をスローする方法では不十分であるということです。
これは、マジック メソッド間の障壁を打ち破り、次のような方法での使用をサポートする唯一のものです。その他のマジック メソッド マジック メソッド呼び出しの特殊なケース!
マジック メソッドの独立性を維持するために、Python は UserString、UserList、UserDict などの派生クラスを導入することに多大な労力を費やしましたが、__missing__() については妥協することを選択しました。 推奨学習:以上がPython マジック関数の学習 __missing__の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。