2011-02-08 14 views
7

希望から基底クラスの値を取得することは、これは十分に明確である:Pythonの:派生クラス

class myParent(): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print myParent.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers() 

私が個別にparentNumberを設定し、子クラスを経由してその数に達しており、この場合には、いくつかのためにそれを使用したいです乗算。

私はOOP領域が新しく、継承に関する一般的なポインタも同様に歓迎されています。

さらに詳しい情報: 私はVFXベースのプロジェクトのためのプロジェクト管理ソリューションを設計しています、そして、彼らはほとんど私を助けることができる方法を確認するために、クラスや継承で遊んでいます。

今、私はトップクラスのProjectと派生クラスShotを持っています。 Shotには、特定のショットの長さを持つself.length変数があります。また、self.lengthとProject.fpsを使用して長さを秒単位で決定するgetLengthInSeconds()メソッドもあります。プロジェクトには、クラスのインスタンスが作成された後にfpsが設定されるsetFps()メソッドがあります。

私は変数に接頭辞selfを使用するのに慣れています。自己以外のより「グローバル」な変数を使ったクラスではあまり実験していません。 。私はすべてのことをグローバルにしても自分自身ではなく、Project.fpsを面倒なく使うことができますが、私は首の髪に「悪いプログラミングの練習」の警告を出しています。おそらくもっと良い、よりきれいな方法がありますか?

編集:

いくつか読みになった後、スーパー()はちょっと危険なようだ、と私は考える必要があるよりも少し。私は主に単一継承クラスを持っていて、ダイヤモンド階層をどのように使用するかについてもわかりません。super()を含まないスーパークラス変数とメソッドにアクセスするより安全な方法はありますか?

編集:私はそれ間違っているすべてのことを考えている場合

オールライトは、これは理にかなっているかどうか。

私はグループと子としてクラスと継承を見ています。子供はそれが親であり、それがすべて価値であることを知っています。子供は別の親に知っていることは親の価値を知っている。私が達成しようとしているのは、すべてのショットをプロジェクトの一部にすることです。そして今、私はProject()クラス内からShot()インスタンスを作成し、そのインスタンスをProject()インスタンス内で管理されているショットのリストに追加します。

すなわち

class myParent(object): 
    def __init__(self): 
     self.parent_id = '' 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name)) 

    def getChildren(self): 
     return self.children 

    def setParentId(self, id): 
     self.parentId = id 

class myChild(myParent): 
    def __init__(self, id): 
     super(myChild, self).__init__() 
     self.id = id 

    def getParentId(self): 
     return self.parent_id 

p = myParent() 
p.setParentId('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId() 

すべての子供がこのよう親の新しいインスタンスを取得しているように、私は一種の...ここにロジックでミスステップが、その周りにいない現実的な方法を見ることができ はそう、どこparent_idは常に空文字列です。

+0

あなたはスーパークラスのコンストラクタを呼び出す必要があります。 –

答えて

5
class myParent(object): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     myParent.__init__(self) 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print self.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers()

あなたは多重継承やその他のボーダーケースを持っていないときは、通常superせずにうまく管理することができますベースクラスが変更された場合は、親クラス名をのinit(およびその他のmyParentを明示的に参照するメソッド)から変更することを忘れないでください。

親の__init__がパラメータを受け取った場合は、その子の__init__から渡す必要があります。

class myParent(object): 
    def __init__(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     myParent.__init__(self, customParam) 
     self.childNumber = 4

あなたはすべての子クラスでcustomParamの繰り返しを嫌う場合は、このように動作します2期工事、と呼ばれる代替OOパターンがあります。このパターンでは

class myParent(object): 
    def customInit(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     self.childNumber = 4 

p = Child() 
p.customInit(10) 
p.multiplyNumbers() 

は、あなたがする必要はありません親のパラメータのいずれかを繰り返したり、子の親の__init__を呼び出すことさえできますが、オブジェクトを作成するときに必ず2次コンストラクタを呼び出すことを忘れないようにする必要があります。そうしないと、オブジェクトは部分的に未初期化のままになります。

UPDATE(更新の質問に答えるために):

あなたはここに親子関係の2つの無関係な概念をミキシングしているようです。継承は型階層に関するもので、所有権階層の後ろにあるようです(is-a対has-a)。

は、私はこのように、あなたの更新されたコードを構造化します:

class myParent(object): 
    def __init__(self, parentId): 
     self.id = parentId 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name, self)) 

    def getChildren(self): 
     return self.children 

class myChild(object): 
    def __init__(self, childId, parent): 
     self.id = childId 
     self.parent = parent 

    def getParentId(self): 
     return self.parent.id 

p = myParent('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId()
+0

あなたの答えをありがとう!あなたは更新された質問を見ていただけますか? –

+0

@Marcus:答えを更新 – shang

+0

はい、それはずっと意味があります。ありがとう! –

5

myParentから初期化を実行するには、Childとするだけです。その後、現在のインスタンス(selfにはのインスタンス属性があり、myParentのインスタンスには("is a")となるので、self.parentNumberを使用できます。これは、super(Child, self).__init__()Child.__init__(理想的には最初の行)に入れることで実現しますが、myParent.__init__(self)でも動作しますが、基底クラスが変更された場合や多重継承の場合は間違っている可能性があります。 Python 3を使用している場合は、すべての引数をsuperにドロップできます。

class C(object): 
    x = ... 

class C(object): 
    def __init__(self): 
     self.x = ... 

前者は非常に異なるCのすべてのインスタンスによって共有されるクラス変数を作成することに注意してください。後者はインスタンス変数を作成し、それぞれのインスタンスにはCというインスタンスがあります。 (同様に、グローバル変数をインスタンスにバインドされていない - しかし、私はあなたが上を話していたと仮定?)

+1

+1 .. 'multiplyNumbers'の' self.parentNumber'にする必要があります。 – sdolan

+0

@sdolan:はい、含まれています。 – delnan

+0

ちょうど私が探していた情報の種類。やってみます。 –