8

これは、私が回避しようとしているものの非常に簡単な例です。

class Test(object):
    some_dict = {Test: True}

問題は、まだ定義されている間は Test を参照できないことです

通常、私はこれを行うだけです:

class Test(object):
    some_dict = {}
    def __init__(self):
        if self.__class__.some_dict == {}:
            self.__class__.some_dict = {Test: True}

しかし、私はこのクラスのインスタンスを作成しません。これは実際には、関連する関数とデータのグループを保持する単なるコンテナーです (私はこれらのクラスをいくつか持っており、それらへの参照を渡します。そのため、Test が独自のクラスである必要があります) 。

だから私の質問は、定義中に Test を参照するにはどうすればよいですか、または__init__クラスが定義されるとすぐに get が呼び出されるのに似たものがありますか? 可能であればself.some_dict = {Test: True}、クラス定義内にとどまりたいです。これは、これまでのところこれを行う方法を知っている唯一の方法です。

class Test(object):
    @classmethod
    def class_init(cls):
        cls.some_dict = {Test: True}
Test.class_init()
4

5 に答える 5

12

クラスは、定義されている間は実際には存在しません。ステートメントが機能する方法は、classステートメントの本体が別の名前空間でコードのブロックとして実行されることです。実行の最後に、その名前空間がメタクラス ( などtype) に渡され、メタクラスは名前空間を属性空間として使用してクラスを作成します。

あなたの説明から、Test がクラスである必要はないようです。代わりにモジュールにする必要があるようです。some_dictはグローバルです-クラス属性であっても、プログラムにはそのような属性が1つしかないため、グローバルを持つよりも優れているわけではありません-クラスにあるクラスメソッドはすべて関数にすることができます。

本当にクラスにしたい場合は、次の 3 つのオプションがあります。クラスを定義した後に dict を設定します。

class Test:
    some_dict = {}
Test.some_dict[Test] = True

クラス デコレーターを使用します (Python 2.6 以降)。

def set_some_dict(cls):
    cls.some_dict[cls] = True

@set_some_dict
class Test:
    some_dict = {}

またはメタクラスを使用します。

class SomeDictSetterType(type):
    def __init__(self, name, bases, attrs):
        self.some_dict[self] = True
        super(SomeDictSetterType, self).__init__(name, bases, attrs)

class Test(object):
    __metaclass__ = SomeDictSetterType
    some_dict = {}
于 2010-04-24T22:41:58.640 に答える
4

メインクラス定義の後に some_dict 属性を追加できます。

class Test(object):
  pass
Test.some_dict = {Test: True}
于 2010-04-24T22:38:15.997 に答える
1

私は過去にこの方法でクラスを使用しようとしましたが、すぐに見苦しくなります (たとえば、すべてのメソッドはクラス メソッドまたは静的メソッドである必要があり、最終的に特定の特殊なメソッドを定義したいことに気付くでしょう)。メタクラスの使用を開始する必要があります)。代わりにクラスインスタンスを使用するだけで、物事がはるかに簡単になる可能性があります-実際には欠点はありません。

他の人が提案したものの(奇妙に見える)代替:使用できます__new__

class Test(object):
    def __new__(cls):
        cls.some_dict = {cls: True}

Test()

__new__クラスへの参照を返し、デコレーターを使用してそれを呼び出すこともできます。

def instantiate(cls):
    return cls()

@instantiate
class Test(object):
    def __new__(cls):
        cls.some_dict = {cls: True}
        return cls
于 2012-06-07T08:32:12.420 に答える
0

メタクラスを使用することもできます (ここでは関数ですが、他の方法があります)。

def Meta(name, bases, ns):
    klass = type(name, bases, ns)
    setattr(klass, 'some_dict', { klass: True })
    return klass

class Test(object):
    __metaclass__ = Meta

print Test.some_dict
于 2010-04-26T07:33:45.407 に答える
0

Thomas の最初の例は非常に優れていますが、これは同じことを行うより Pythonic な方法です。

class Test:
    x = {}
    @classmethod
    def init(cls):
        # do whatever setup you need here
        cls.x[cls] = True
Test.init()
于 2012-06-07T08:13:26.223 に答える