2016-05-20 29 views
0

私は 'アラーム'を定義するクラスを持っていて、次に 'httpalarm'を定義するクラスを持っています。今、httpalarmは、アラームのものと同じプロパティの多くを共有しています(実際には、すべて同じものとそれ以外のものがあります)。オブジェクトは親オブジェクトからプロパティを継承します

これらのプロパティをアラームオブジェクトの一部として一度定義してから、httpalarmをアラームの子として作成すると、すでにすべてのプロパティが取得されるはずです。しかし、それはしません。少なくとも、それは現れていません。私はアラームオブジェクトを作成するときに

class alarm(object): 
    def __init__(self, severity, name, eventId): 
     self.severity = severity 
     self.name = name 
     self.eventId eventId 


class httpalarm(alarm): 
    def __init__(self, **kwargs): 
     self._dict__.update(kwargs) 

は今、私は私が期待するものを手に入れる:

a = alarm('Critical', 'Name', '0x800111') 

vars(a) 
-> 
{'severity': 'Critical', 'name': 'Name', 'eventId': '0x800111'} 

予想通りこれがあります。しかし、私がhttpalarmを作成するとき:

b = httpalarm(test = 'Test') 
vars(b) 
-> 
{'test': 'Test'} 

これは予想外です。私は、httpalarm bに重大性、名前、およびeventId属性がすでに設定されていることを予期していました。いいえ、私は再びテストしhttpalarmに変更して再び

class alarm(object): 
    severity = 'Warning' 
    name = None 
    eventId = None 

と;:

そうではなく、インスタンスのプロパティは、私はクラスのプロパティを使用するには、アラームクラスを設定します

c = httpalarm(test='Test') 

vars(c) 
-> 
{'test': 'Test'} 

また、varsは他のすべてのプロパティを表示していません。しかし、彼らは次のように設定されています。

print c.severity 
'Warning' 

継承されたプロパティを印刷するように見えます。そして、オブジェクトが実際にここで起こっていただきました!私は本当にわからないんだけど、すべてのプロパティ

dir(c) 
-> 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'eventId', 'name', 'severity', 'test'] 

を返さない表示するにはDIR(C)を使用。同じプロパティを常に定義しなくて済むように継承できるアラームクラスを作成したいと思います。

d = httpalarm(severity = 'Critical', name = 'Name', eventId = '0x800111', test = 'test') 

とhttpalarmインスタンスがすべてのアラームのプロパティだけでなく、独自のhttpalarmクラスからプロパティを含めるdは持っている:私は何を取得しようとしていることです。

編集:

class httpalarm(alarm): 
    def __init__(self, 
       **kwargs): 

     super(httpalarm, self).__init__() 
     for k,v in self.__dict__.iteritems(): 
      if type(v) == tuple: 
       setattr(self, k, v[0]) 

     self.__dict__.update(kwargs) 

答えて

1

あなたはalarmのコンストラクタを自分で呼び出す必要があります:

class httpalarm(alarm): 
    def __init__(self, **kwargs): 
     super(httpalarm, self).__init__() 
     # Your code here 

なぜ使用して予想通り、私はこの作業は、作業持っているコーリーBrigmanから提出後 これは特にここに必要ですか? Pythonのオブジェクト実装は、C++やJavaなどの他の言語とは大きく異なります。オブジェクトがどのように作成されるかで多くのことをしなければなりません。

C++オブジェクトは、基本的に、いくつかの関数がアタッチされたメモリ構造です。 Pythonオブジェクトは、いくつかの関数が付属する辞書のようなものです。これはどのように再生されますか?2のように、初期化(C++でコンストラクタ、およびPythonで__init__);両方の環境で

、あなたが作成を想像することができることは(Pythonでクラスの関数として__new__newが、通常はC++での舞台裏)別々の作品。

C++では、オブジェクトの操作にメモリ構造が不可欠であるため、new(上位レベル)を呼び出すと、適切なサイズで宣言された各属性にスペースが割り当てられます。これは静的です。新しいアトリビュートを即座に作成することはできません。宣言したアトリビュートのみを変更することができます。これはまた、サブクラス化するときに構造体がどのように見えるかを正確に宣言しているので、コンパイラが適切なメモリイメージを構築できるようにする必要があります。

次に、コンストラクタを呼び出します。コンストラクタは、実際には入力に基づいて値を初期化し、プログラマが望むものはすべて初期化します。多くの場合、初期化されたデフォルト値に満足すれば、実際にはコンストラクタをC++のままにしておくことも、宣言して空のままにすることもできます。

Pythonでは、オブジェクトモデルが変更可能なdictに似ているため、基本クラスの動作( '辞書を作成してオブジェクトに添付する')はその辞書を作成することです。これは通常、ほとんどの用途では十分です。したがって、Pythonでは__new__関数が書かれた(*)ことはほとんどありません。

代わりに、ほとんどの人のデフォルトでは、__init__関数の変数を初期化しています。重要なことは、オブジェクトが作成された後にの後にと呼ばれることです。次に、必要な変数を任意のデータ(任意のタイプのもの)に設定できます。

いずれの場合も、オブジェクトはの前に作成され、の前にイニシャライザが呼び出されます。 C++では、作成によってデータ構造が作成されます。 Pythonでは、オブジェクトの作成(通常)は辞書を作成するだけです。alarm.__init__httpalarm.__init__というエントリには、両方のオブジェクトが空の辞書のように見えます。 initは必要な属性を作成する必要があります。 C++でベースクラスのコンストラクタを呼び出すのは珍しいことではありませんが、ベースクラスのコンストラクタもサブクラスで使用される共通の属性を作成するため、Pythonではさらに一般的です。

スロットを使用することができます。スロットはC++の仕組みに近いが、正確には使用できません。 varsについては

- あなたは__init__または他の場所に設定したもの - varsローカル属性を示しています。それらをクラス変数として宣言すると、dirに表示されます。これは、クラス属性とローカルに設定されたオブジェクト属性の両方を示しますが、varsではないためです。ドキュメンテーション文字列から:

vars([object]) -> dictionary 

Without arguments, equivalent to locals(). 
With an argument, equivalent to object.__dict__. 

クラス変数はobject.__class__.__dict__の代わりobject.__dict__です。

実際にその動作をしたい場合は、実際にメタクラスを使用して、__new__関数をオーバーライドしてデフォルトの属性を作成できます。それは一般的ではありませんが、C++のように動作します(私が知っている限り...私はあまりそれをしていません)。しかし、プロパティが(必ず)クラス属性であり、オブジェクトに対して動的に設定することはできないため、時には(通常は「メタプログラミング」などと呼ばれます)、動的プロパティを使用する場合は特にそうです。代わりに、必要な属性を動的に追加するクラスファクトリを使用します。

関連する問題