Python探索UserDict:パッケージクラス

4770 ワード

ご覧のように、FileInfoは辞書のような行動をするクラスです.この点をさらに明らかにするために、私たちのFileInfoクラスの親であるUserDictモジュールのUserDictクラスを見てみましょう.特に何もありませんPythonで書いてあり、1つに保存されています.pyファイルには、私たちの他のコードのようなものがあります.特に、Pythonインストールディレクトリのlibディレクトリの下に保存されています.
1.UserDictクラスの定義
class UserDict:                                (1)
    def __init__(self, dict=None):             (2)
        self.data = {}                         (3)
        if dict is not None: self.update(dict) (4) (5)

(1)UserDictは他のクラスから継承されていないベースクラスであることに注意する.
(2)これが我々がFileInfoクラスで上書きした_init__ 方法.この親のパラメータリストは、子とは異なることに注意してください.各サブクラスは、正しいパラメータを使用して親クラスを呼び出すだけで、独自のパラメータセットを持つことができます.ここで親クラスには、dictパラメータに辞書を渡すことによって初期値を定義する方法があります.この方法では、FileInfoは使用されません.(3)Pythonはデータ属性(JavaとPowerbuilderでは「インスタンス変数」、C++では「データメンバー」と呼ぶ)をサポートし、特定のクラスインスタンスが所有するデータである.この例では、各UserDictインスタンスにdataデータ属性があります.クラス外のコードからこの属性を参照するには、インスタンスの名前で定義する必要があります.instance.data、限定の方法はモジュールの名前で関数を限定するのと同じです.クラスの内部でデータ属性を参照するには、selfを制限子として使用します.習慣的に、すべてのデータ属性は__にあります.init__ メソッドで意味のある値に初期化します.しかし、これは必須ではありません.データ属性は、ローカル変数のように、初めて値を与えたときに突然発生します.(4)updateメソッドは、ある辞書のキーと値をすべて別の辞書にコピーする辞書レプリケーションです.この操作は、ターゲット辞書を事前に空にしないで、ターゲット辞書にキーがすでに存在する場合は上書きされ、ターゲット辞書にキー名が存在しない場合は変更されません.updateはコピー関数ではなくマージ関数と見なすべきです.
(5)この文法は以前読んだことがないかもしれません(私はまだこの本の例で使ったことがありません).これはif文ですが、次の行に縮小ブロックはありません.コロンの後ろにあるだけで、同じ行に単一の文があります.これは完全に合法的で、1つのブロックに文が1つしかない場合の簡略化にすぎません.(C++に括弧で囲まれた単一行文が含まれていないようなものです.)この構文を使用するか、後ろの行に縮小コードを書くことができますが、同じブロックに対して同時に2つの方法を使用することはできません.
Note:Python v s.Java:Function Overloading JavaとPowerbuilderは、1つのクラスに同名の複数のメソッドがあることをサポートしていますが、これらのメソッドは、パラメータの個数が異なるか、パラメータのタイプが異なるかのいずれかです.他の言語(PL/SQLなど)では、パラメータ名によるリロードもサポートされています.つまり、クラスには同じタイプ、同じ数のパラメータがありますが、パラメータ名が異なります.Pythonはどちらもサポートされていませんが、とにかく形式的な関数のリロードはありません.一つ_init__ 方法は一つです.init__ メソッドは、どのようなパラメータがあっても構いません.クラスごとに1つしかありません_init__ メソッド、およびサブクラスが1つの__を持つ場合init__ メソッドは、常に親の__を上書きします.init__ メソッドは、サブクラスでも異なるパラメータリストで定義できます.Note:Pythonの原作者Guido氏は、「子クラスは親クラスのメソッドを上書きすることができる.メソッドには特別な優先度設定がないため、親クラスの1つのメソッドは、親クラスの別のメソッドを呼び出すときに、実際には子クラスで親クラスの同名メソッドを上書きするメソッドを呼び出す可能性がある.(C++プログラマーは、すべてのPythonメソッドが虚関数だと思っているかもしれません.)」もしあなたが分からないなら(それは私を困惑させます)、気にする必要はありません.スキップすると思います.Caution:いつも_にいるはずinit__ メソッドでは、インスタンスのすべてのデータ属性に初期値を付与します.これにより、初期化されていない(つまり存在しない)属性の使用によるAttributeErrorの異常な時間をキャプチャするのに時間がかかりません.
2.UserDictの一般的な方法
    def clear(self): self.data.clear()          (1)
    def copy(self):                             (2)
        if self.__class__ is UserDict:          (3)
            return UserDict(self.data)         
        import copy                             (4)
        return copy.copy(self)                 
    def keys(self): return self.data.keys()     (5)
    def items(self): return self.data.items()  
    def values(self): return self.data.values()

(1)clearは通常のクラスメソッドであり,いつでも誰にでも公開的に呼び出される.clearは、selfを最初のパラメータとして使用するすべてのクラスメソッド(従来または専用)と同様であることに注意してください.(メソッドを呼び出すときはselfを含まなくてもいいことを覚えておいてください.このことはPythonがあなたのためにしたのです.)このクラスをカプセル化する基本技術にも注意してください.真の辞書(data)をデータ属性として保存し、すべての真の辞書が持つ方法を定義し、各クラスの方法を真の辞書上の対応する方法にリダイレクトします.(辞書のclearメソッドは、すべてのキーワードとキーワードに対応する値を削除することを忘れているかもしれません.)
(2)本物の辞書のcopyメソッドは、元の辞書のそのままのコピーである新しい辞書を返します(すべてのキー-値ペアは同じです).しかし、UserDictは簡単にselfにリダイレクトすることはできない.data.copyは、その方法が本当の辞書を返すため、selfのように同じクラスの新しいインスタンスを返すことを望んでいます.
(3)我々は_class__ 属性はselfがUserDictであるかどうかを表示します.もしそうであれば、よかったです.私たちはどのようにUserDictをコピーするかを知っています.新しいUserDictを作成し、本物の辞書に伝えるだけで、この辞書はselfに保存されています.dataが当たった.すぐにこの新しいUserDictに戻り、次の行でimport copyを使用する必要もありません.
(4)self._の場合class__ UserDictではなく、selfは必ずUserDictのサブクラス(FileInfoの可能性がある)であり、生活にはいつも意外なことがある.UserDictは、そのサブクラスのそのままのコピーを生成する方法を知らない.たとえば、サブクラスに他のデータ属性が定義されている可能性があるため、完全にコピーし、すべての内容をコピーしたと判断するしかない.幸いなことに、Pythonはモジュールを持っていて、copyと呼ばれています.ここでは詳細を知りたくありません(しかし、それは絶対にクールなモジュールです.自分で研究したいと思っていますか?)copyがPythonオブジェクトをコピーできると言ったら十分です.これが私たちがここで使っている理由です.
(5)残りの方法はselfに直接リダイレクトする.dataの内蔵関数にあります.
Note:Python 2.2以前のバージョンでは、文字列、リスト、辞書などの組み込みデータ型を直接サブクラス化することはできません.補償として、Pythonは、UserString、UserList、UserDictなどの組み込みデータ型の動作をシミュレートするパッケージクラスを提供する.一般的な方法と特殊な方法を混在させることで、UserDictクラスは辞書をうまく模倣することができます.Python 2.2以降のバージョンでは、dict内蔵データ型から直接継承できます.本書fileinfo_fromdict.pyにはこの方面の一例がある.例に示すように、Pythonでは、組み込みデータ型dictを直接継承することができます.これにより、UserDictとは3つの点が異なります.
3.内部構築データ型dictから直接継承
class FileInfo(dict):                  (1)
    "store file metadata"
    def __init__(self, filename=None): (2)
        self["name"] = filename

(1)最初の違いは、dictが既に使用可能な組み込みデータ型であるため、UserDictモジュールをインポートする必要がないことです.2つ目の違いはあなたがUserDictから受け継いだのではないことです.UserDictではなく、dictから直接継承されます.
(2)3つ目の違いは難解ですが、重要です.UserDict内部の作業方法は、手動で呼び出すことを要求しています.init__ メソッドは、内部データ構造を正しく初期化します.dictはこのように動作せず、パッケージではないので明確な初期化は必要ありません.