2015-12-06 7 views
5

残念ながら、Pythonでは、クラス属性はクラス名を参照できません。以下はnameerror提起:クラス属性は、(私の場合は、ライブラリーの検証スキームのその一部)そのクラス名を参照しなければならない状況ではclass属性のクラス名を参照する最良の方法は何ですか?

class Foo(object): 
    bar = Foo 

を行うための明確な方法は何でありますそう?

class Foo(object): 
    bar = None 
Foo.bar = Foo 

これは動作しますが、でも、コメントはクラス属性が宣言時に初期化されるように、ないクラスが宣言された後に期待しているので、混乱を引き起こす可能性がある:

次は私の現在の試みです。

もっと良い回避策がありますか?

答えて

2

あなたはクラスが定義されていると、プレースホルダ文字列を置き換えクラスのデコレータを定義することができます:

def fixup(cls): 
    placeholder = '@' + cls.__name__ 
    for k,v in vars(cls).items(): 
     if v == placeholder: 
      setattr(cls, k, cls) 
    return cls 

@fixup 
class Foo(object): 
    bar = '@Foo' 

print('Foo.bar: {!r}'.format(Foo.bar)) # -> Foo.bar: <class '__main__.Foo'> 
+0

クラス名をクラス内の文字列にハードコーディングしないようにするには、プレースホルダを ''''のような定数にハードコードすることができます。 – martineau

1

use metaclassesです。 __new__を定義し、セットアトリビュートを反復処理し、バックポインタをクラス自体に設定します。

+0

どのようにこれを行うことができますか?私の理解では、Pythonはすべてのクラス属性が解析されるまでクラスオブジェクトを作成しません。なぜこの問題が存在するのか。 – PaintingInAir

+0

'__new__'は、クラス定義が終了した後に実行されます。次に、定義されたすべての属性を繰り返し処理し、クラス自体へのポインタを設定するコードでそれらを「修正」します。 –

+0

下記のクラスデコレータソリューションが優れています。私はそれをお勧めします。 –

0

「エイリアス」「__class__」だけにしたい場合は、なぜプロパティを使用しないのですか?

@property 
def bar(self): 
    return self.__class__ 

これは、いくつかの継承で遊ぶと問題が発生することになります。その後、

@moi('bar') 
class Foo(object): 
    pass 

:あなたは

def moi(fieldname): 
    def _selfref(cls): 
     setattr(cls, fieldname, cls.__name__) 
     return cls 

    return _selfref 

用法クラスデコレータを使用することができます

+0

これは、コールバーにクラスのインスタンスが必要なので、クラス属性でクラスを使用することを許可していないようです。 – PaintingInAir

+0

しかし、どのようなシナリオで、クラス自体を参照するクラス属性が必要になりますか?プロパティを参照するものは、単にクラスオブジェクト自体を参照することができますか? –

+0

あなたは両方のデコレータを使用できますか: '@ property'と' @ classmethod'? (それがうまくいかないのはなぜですか?) – bperson

1

メタクラスを使用して自動的に設定します。

def my_meta(name, bases, attrs): 
    cls = type(name, bases, attrs) 
    cls.bar = cls 
    return cls 


class Foo(object): 
    __metaclass__ = my_meta 


>>> print Foo.bar 
<class '__main__.Foo'> 
関連する問題