2012-06-29 3 views
6

余談スタートこの単純なpythonメタクラスで何が問題になっていますか?

私はPythonであるかメタクラスを学びました。私は、Pythonの作成者が誰もがそれらを使用したかったとは思わない。私は、ほとんどの場合、クラスではないかもしれないメタクラスが、このコンセプトからほとんどの人を迂回させるのに十分な名前であることを意味しています!私の質問にオン

余談エンド

。私はこの単純なメタクラスを書いて、モジュールで作成されたすべてのクラスにデフォルトのドキュメント文字列を追加しました。しかし、それが動作していません。

def metest(cls,name,bases,dict): 
    cls.setattr(cls,'__doc__',"""Default Doc""") 
    return type(cls,(),{}) 

__metaclass__=metest 

class test(object): 
    pass 

print test.__doc__ 

t=test() 

print t.__doc__ 

出力:

None 
None 

は私が間違って何をやっているの?

答えて

3

私はあなたの例の作品を作った:

def metest(name, bases, dict): 
    print name, bases, dict 
    dict['__doc__'] = """New Doc""" 
    cls = type(name+"_meta", bases, dict) 
    return cls 

class Test(object): 
    "Old doc" 
    __metaclass__ = metest 

print Test 
print Test.__doc__ 

t = Test() 

print t.__doc__ 
  1. 使用される "メタクラス" を作成します。
  2. 「クラス作成機能」の署名を修正します。 clsは私たちによって作成されます。
  3. 区別するために「古い」および「新しい」ドキュメントストリングがあります。
+0

グローバルメタクラスを使用することは可能ですが、単にオブジェクトから継承しないでください –

+0

オブジェクトから継承してはいけないのは誰ですか?モジュールのメタクラスまたはすべてのクラス? – ritratt

2

この回答を参照してください:object基本クラスを提供Python metaclass and the object base class

は、モジュールレベルのメタクラスをオーバーライドし、typeobjectのメタクラス)に置き換えられます。

さらに、メタクラスには欠陥があり、適用する場合でも(クラス内に__metaclass__を設定して)機能しません。それは3つの引数だけを受け入れるべきです。通常、メタクラスは通常クラスなので、それは余分な「自己」引数を受け入れるためです(メタクラスの場合は慣習的にと呼ばれています)。

4

グローバルアプローチに完全に精通していないので、__metaclass__のように設定してください。私が知っているすべての、その別の有効なスタイル。

しかし、私は精通しています何の例を提供します:

class MeTest(type): 
    def __new__(cls,name,bases,dict): 
     dict['__doc__'] = """Default Doc""" 
     return type.__new__(cls,name,bases,dict) 

class Test(object): 
    __metaclass__ = MeTest 
+0

メタクラスとしての機能を使ってやりたいです。 – ritratt

1

おそらくこれはあなたが望むものです。あなたはグローバルメタクラスを使用したい場合は

def metest(name, bases, dct): 
    dct['__doc__'] = """Default Doc""" 
    return type(name, bases, dct) 

__metaclass__=metest 

class test: 
    pass 

print test.__doc__ 

t=test() 

print t.__doc__ 
+0

しかし、メタクラスは必然的にタイプではないでしょうか?私が理解していることから、Pythonのすべてのクラスは 'type'クラスのオブジェクトです。だから私はすべてのクラスを変更したい場合は、 'メタクラス 'がする' type'をオーバーライドする必要があります。それではなぜ 'type'から継承してはいけないのですか?それは、オーバーライドされていない 'type'クラスを継承するからですか?私は混乱しています。 :S – ritratt

+0

@ litratt、 'metest'は、type_から継承しているクラスを_returns_する関数です。グローバルな '__metaclass __ = metest'は古典的なクラスでのみ動作します。 'object'から継承すると、クラスが再びメタクラスをオーバーライドしない限り、メタクラスを' type'に戻します –

1

ことを行うことはできませんのでobjectから継承するメタクラスtypeになるだろう、あなたのモジュールレベルのメタクラスはBrenBarnにより上記と同様に、上書きされます。 これを修正するには、クラスインスタンスとして設定する代わりに、 return clsにコードを作成してください。

関連する問題