pythonクラスとメタクラス(metaclass)の理解と簡単な運用


(一)pythonのクラス
今日は良い文を見て、自分の状況に合わせてまとめました.ここで議論するpythonクラスは、python 2に基づいている.7 xおよびobjectに継承された新しいクラスについて議論する.
まずpythonでは、すべてのものがオブジェクトです.この言葉はとても重要です.メタクラスを理解するにはpythonのクラスを再理解します.
class Trick(object):
    pass

pythonがclass文を実行すると、クラスオブジェクトがメモリに初期化されます.たとえば、Trickオブジェクトを初期化します.このオブジェクト(クラス)自体は、オブジェクト(通常はインスタンスですがpythonではオブジェクト)を作成する能力を持っています.
後続の理解を容易にするために、新しいクラスの中で最も古いすごいキーワードtypeを試してみましょう.
input:
class Trick(object):
pass

print type('123')
print type(123)
print type(Trick())

output:




通常使用しているstr,int,および初期化したインスタンスオブジェクトTrick()が得られることがわかります.
しかし、次の方法は見たことがないかもしれませんが、typeは同じようにクラスを動的に作成することができます.
type(クラス名、親のメタグループ(継承の場合は空)、属性を含む辞書(名前と値)
これはどうやって使いますか?この方法でクラスを作成します.次のコードを見てみましょう.
input:
print type('trick', (), {})

output:

              

input:
print type('trick', (), {})()

output:
<__main__.trick object="" at="">

ここでtrickのインスタンスオブジェクトが表示されます.
同じ方法では、クラスを作成する親を初期化したり、クラスのプロパティを初期化したりすることもできます.
input:
class FlyToSky(object):
    pass

pw = type('Trick', (FlyToSky, ), {'laugh_at': 'hahahaha'})
print pw().laugh_at
print pw.__dict__
print pw.__bases__
print pw().__class__
print pw().__class__.__class__


output:
hahahaha
{'__module__': '__main__', 'laugh_at': 'hahahaha', '__doc__': None}
(,)



次に、上記の内容を順番に整理します.その前に、2つの魔法の方法を紹介しなければなりません.
  • __class__この方法は、python内のすべてのものがオブジェクトであり、クラスオブジェクトもオブジェクトであることを理解するために、オブジェクトがどの生成されたかを表示するために使用されます.以前の考え方で考えると,クラスはメタクラスのインスタンスであり,インスタンスオブジェクトはクラスのインスタンスである.
  • __bases__このメソッドは、オブジェクトの親が誰であるかを得るために使用されます.特に注意してください.base__単一の親を返します.bases__すべての親をtuple形式で返します.

  • はい、この2つの方法がわかりました.私は順番に行ごとにどういう意味かを話します.
  • typeを使用してpw typeに付与された3つのパラメータを作成する意味分解は(クラスの名前、クラスに親がいるかどうか()、クラスの属性辞書{})
  • である.
  • ここではクラスのインスタンスを初期化し、親クラスのlaugh_を取得しようとします.at属性値を求め、結果hahahahaha
  • を得た.
  • pw、すなわち、一般的なクラスのクラス辞書データ
  • を取得します.
  • pwの親を手に入れた結果、私たちが指定したFlyToSky
  • pwのインスタンスpw()はどのクラスに属するか初期化され、class Trick
  • であることがわかる.
  • class trickは誰が初期化したのか見てみましょう.メタタイプです
  • (二)メタ類とは何か、簡単な運用
    このすべての紹介が終わったら、私たちはやっと本題に入ることができます.
    いったい何が元類なのか.一般的には、メタクラスはクラスを作成するクラスです.のこれは超抽象的に聞こえますか?これを見てみましょう
    Trick = MetaClass()
    MyObject = Trick()
    

    Trickで直接できることを紹介しました
    Trick = type('Trick', (), {})
    

    これは、Typeが実際にはメタクラスであり、クラスを作成することができるからです.メタクラスとはさっき言ったように、メタクラスはクラスを作成するクラスです.彼はクラスの工場を作ったとも言える.
    クラスの上の_metaclass__属性、元類の細部を理解したいと信じている盆友は、このものを見たことがあるに違いないし、好奇心を持っている.さもないと何があなたを支えてここを見たのか分かりません.の使用しました_metaclass__この魔法の方法は__を使うことを意味しますmetaclass__指定したメタクラスがクラスを作成します.
    class Trick(FlyToSky):
        pass
    

    上記のクラスを作成するとpythonは、Trickに__があります.metaclass__この属性ですか?ある場合、Pythonはメモリを通過します.metaclass__Trickという名前のクラスオブジェクト、つまりTrickというものを作成します.Pythonが見つからなかったらmetaclass__,自分の親FlyToSkyの中で探し続けます.metaclass__を選択し、metaclass__指定した方法でTrickクラスオブジェクトを作成します.Pythonがどの親にも見つからない場合_metaclass__,あきらめずに、モジュールの中にあるかどうかを探します.metaclass__を選択して設定できます.まだ見つからない場合は、デフォルトのtypeを使用してTrickを作成します.
    では、問題が来ました.私たちは_metaclass__の中に何を置きますか?答えはクラスを作成できるもの、type、またはtypeやサブクラス化typeを使用するものであれば何でもいいです.
    (三)カスタムメタクラス
    クラスをカスタマイズする目的は、クラスの作成をブロックし、プロパティを変更してクラスに戻ることです.ちょっと熟知しているのではないでしょうか.そう、装飾器がやったような気がしますが、装飾器は関数を修飾しているだけで、同じものが入っていて、追加されて、最後に返されます.
    実は上で述べた制定の1つを除いてmetaclass__必ずしも正式なクラスではなく、関数であってもよい.すべてのモジュールレベルがこのメタクラスでクラスを作成するには、モジュールレベルで__を設定します.metaclass__それでいいです.まず1つ書いてみてください.私はstackoverflowの上の友达の例を延長して、すべての属性を大文字に変更します.?
    この例を見てみましょう.
    input:
    def upper_attr(class_name, class_parents, class_attr):
        """
              ,           
        :param class_name:      
        :param class_parents:     tuple
        :param class_attr:     
        :return:    
        """
        #      generator
        attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__'))
        uppercase_attrs = dict((name.upper(), value) for name, value in attrs)
        return type(class_name, class_parents, uppercase_attrs)
    
    __metaclass__ = upper_attr
    
    pw = upper_attr('Trick', (), {'bar': 0})
    print hasattr(pw, 'bar')
    print hasattr(pw, 'BAR')
    print pw.BAR
    
    output:
    False
    True
    0
    

    上から見ると、メタクラス(metaclass)を実装し、モジュールがこのメタクラスを使用してクラスを作成することを指定したので、typeを使用してクラスを作成すると、小文字のbarパラメータが大文字のBARパラメータに置き換えられ、最後にこのクラス属性を呼び出して印刷されたことがわかります.
    上では関数を使用してメタクラスをクラスに渡し、次に正式なクラスを使用してメタクラスとして__に渡します.metaclass__
    class UpperAttrMetaClass(type):
        def __new__(mcs, class_name, class_parents, class_attr):
            attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__'))
            uppercase_attrs = dict((name.upper(), value) for name, value in attrs)
            return super(UpperAttrMetaClass, mcs).__new__(mcs, class_name, class_parents, uppercase_attrs)
    
    
    class Trick(object):
        __metaclass__ = UpperAttrMetaClass
        bar = 12
        money = 'unlimited'
    
    print Trick.BAR
    print Trick.MONEY
    

    まとめ:ああ疲れた疲れたやっと書き終わった...長い間書いていましたが、とにかく私が言ったように、装飾器の考え方を少し持って元類を理解することは、あなたを明るくするかもしれません.元類という暗い魔法は常識的に広く使われるべきではなく、業務コードを書くことから1年も差がなく、keplerプロジェクトを完成させるときに少し黒い魔法を使った(実際にはこのような操作は必要ない)以外、他の場所では使われたことがない.本当に必要になったら、なぜ使うのかを考えるのではなく、問題を解決するためにこのように書くので、メタ類というものが現れたのかもしれません.私はこのように理解して、1つのものの存在の本当の意味はあなたがこれを使って以前解決しにくい問題を解決することができて、解決しにくい問題を簡単にすることができて、技術を誇示するために1つの問題を複雑にするのではありません.
    Reference:http://blog.jobbole.com/21351/ Pythonのメタhttp://stackoverflow.com/ques... What is metaclass in Pythonを深く理解する