0

クラス属性として空のリストを持つ基本クラスがあります。多くの子クラスは、この基本クラスから継承します。その意図は、このリスト クラス属性をクラス メソッドと組み合わせて使用​​して、各子クラスが独自のインスタンスの特定のセットを追跡できるようにすることです。各クラスには、独自のインスタンスのみを含む個別のリストがあるはずです。

この継承スキームの単純な実装を作成したとき、デバッグ中に、実際にはすべての子クラスがクラス属性とまったく同じリストを共有していることに気付き、Python が参照によってリストを渡すという事実をもう一度楽しんでいました。よく調べてみると、親のすべてのクラス属性、メソッド、および値は、参照によってすべての子に渡されるだけであり、特定の属性が子の定義で明示的にオーバーライドされない限り、これは変更されないようです。

作成時に子のクラス変数を再初期化する最良の方法は何ですか? 理想的には、すべての子が cls.instances 属性で始まることを保証する方法が必要です。これは、どの子にも余分なコードを含まない一意の空のリストです。そうでなければ、そもそも何のために継承に悩まされているのでしょうか? (それには答えないでください)

4

4 に答える 4

3

@DanielRosemanと彼の洞察に満ちた答えを軽視することはありませんが、メタクラスを使用して達成したいことを理解する方法を正確に書き留めると思いました:

mc.py:

class Meta(type):
    def __init__(cls, name, bases, attrs):
        cls.foo = []

class A:
    __metaclass__ = Meta

class B(A):
    pass

これを考えると:

>>> import mc
>>> mc.A.foo
[]
>>> mc.A.foo.append(1)
>>> mc.A.foo
[1]
>>> mc.B.foo
[]
于 2012-05-18T20:45:14.380 に答える
1

これは、おそらくメタクラスに入る必要があるポイントです。あなたが言っているのは、新しい子クラスを定義するたびに、新しい変数のセットが必要になるということです。したがって、メタクラスはクラスタイプのクラスです。つまり、サブクラスを定義するたびに、メタクラスの新しいインスタンスをインスタンス化します。各メタクラスインスタンスは独自のインスタンス変数を持つことができます。つまり、各サブクラスは独自のクラス変数のセットを取得します。

Marty Alchinのブログには、メタクラスを使用してこの種のことを行う方法についてのすばらしい記事があります。

于 2012-05-18T20:34:25.980 に答える
0

ここで直面している問題は、クラスが実際にはオブジェクトであり、クラスのメンバーがtypeそのインスタンスのメンバーではなく、クラスの型オブジェクトのメンバーであるということだと思います。その観点から、サブクラスが実際に親のクラスレベルのメンバーの一意のインスタンスを持たない理由を簡単に理解できます。私が過去にこの種の問題を解決するために使用した方法は、親のクラス変数をディクショナリにし、次に、ディクショナリに格納されているキーの下のリスト.instancesに、親のメソッドで各子のインスタンスをカタログ化することです。タイプです。親スコープ内からでも、onを実行すると、ローカルスコープのタイプではなく、オブジェクトが直接作成されたタイプが得られることを忘れないでください。__init__.instancesselftype()self

于 2012-05-18T20:35:27.420 に答える
0

次のような意味ですか。

    >>> class Foo():
    ...   alist = []
    ...   def __init__(self):
    ...     pass
    >>> foo = Foo()
    >>> foo.alist
    []
    >>> Foo.alist
    []
    >>> Foo.alist.append(7)
    >>> Foo.alist
    [7]
    >>> foo.alist
    [7]
    >>> foo2 = Foo()
    >>> foo2.alist
    [7]
于 2012-05-18T20:32:23.727 に答える