2011-12-27 15 views
4

私は基本クラスから継承されたクラスレベルの辞書を更新するクリーンで簡単な方法を探しています。Pythonが継承したクラスレベルの辞書を更新しました

class Foo(object): 
    adict = {'a' : 1} 

class Bar(Foo): 
    adict.update({'b' : 2}) # this errors out since it can't find adict 

よう:例えば

Foo.adict == {'a' : 1} 
Bar.adict == {'a' : 1, 'b' : 2} 

私はここのインスタンスを使用しないことを好む、そして可能ならばどちらかのクラスメソッドを使用していないと思います。

答えて

3

これが機能したとしても、新しい辞書を作成するのではなく、同じ辞書を更新することになります(Foo.adict is Bar.adict、したがってFoo.adict == Bar.adict)。いずれの場合においても

、最も簡単な方法は、明示的に(上記を参照し、それをコピーする)親クラスの辞書を参照することです:

class Bar(Foo): 
    adict = dict(Foo.adict) 
    adict.update({'b': 2}) 
+0

おかげ - これは間違いなく動作します - 私は(スーパーなどのように)もう少し一般的な何かを見つけ出すことができると期待していた以外にも、明示的に親クラスを参照伴いませんでした継承。 – gnr

+0

クラス辞書を使用しているので、実際にはここで多くの継承を使用していません。代わりに、単にグローバルディクテーションにすることができます。同じ効果。 –

0

「私はここのインスタンスを使用しないことを好む、そして可能ならばと思いますクラスメソッドも使用しないでください。

右。そうしないでください。

foo_adict = {'a' : 1} 

def B(): 
    foo_adict.update({'b': 2}) 

私はあなたのクラス属性レベルの辞書を使用する理由、それはめったに便利か期待されるように動作していないかわかりません。

+0

クラスメンバ*が持っています*。確かに、彼らは進歩していますが、グローバルとほとんど同じではなく、等価でもありません - クラスごとに別々の値を(私のコードスニペットのように)持つことができます。私が今作業しているコードベースは、いくつかの場所でクラスメンバーを使用していますが、それは重いメタプログラミングのためのものです。論理的なグループ化をより明白にすることに加えて、 'classmethod'は彼らが*どこかで働いているデータを取得する必要があります。 – delnan

+0

のクラスメンバが使用しています。クラスメンバー*辞書*(または他の変数)は通常そうではありません。 –

+0

少しの文脈を与えるために、私はこの組織の方法を使ってAPIを構築しています。例えば、私はFoo.adict ['a']とBar.adict ['a']が異なる値で初期化することができるようにしたいと思いますが、大部分の変数は同じになります。クラス定義後に辞書は変更されません。私はまた、継承されていない静的属性を持つためにFooとBarが必要です。なぜクラスメンバーの辞書を使うのが本質的に悪いのか分かりません。 – gnr

0

この問題も発生しました。私はまた、多重継承で動作する可能性がある、メタクラスを使用して、それを解決:

import six 


class CheckerMeta(type): 

    def __new__(cls, name, bases, attrs): 
     new_class = super(CheckerMeta, cls).__new__(cls, name, bases, attrs) 

     base_configs = [bc.config for bc in bases if hasattr(bc, 'config')] 
     configs = base_configs + [new_class.config] 

     new_class.config = {} 
     for config in configs: 
      new_class.config.update(config) 

     return new_class 


class BaseChecker(six.with_metaclass(CheckerMeta)): 
    config = {} 


class CheckerA(BaseChecker): 
    config = {'a': 1} 


class CheckerB(BaseChecker): 
    config = {'b': 2} 


class CheckerC(CheckerA, CheckerB): 
    config = {'c': 3} 


assert CheckerA.config == {'a': 1} 
assert CheckerB.config == {'b': 2} 
assert CheckerC.config == {'a': 1, 'b': 2, 'c':3} 
0

初期adictFooクラスとBarupdateその後、superinitを呼び出すことで初期化します。

class Foo(object): 
    def __init__(self): 
     self.adict = {'a': 1} 


class Bar(Foo): 
    def __init__(self): 
     super(Bar, self).__init__() 
     self.adict.update({'b': 2}) 

例:

In [14]: b = Bar() 
In [15]: b.adict 
Out[15]: {'a': 1, 'b': 2} 
関連する問題