2012-01-13 14 views
23

私はPythonを学んだばかりのJavaの人です。私は冗長なコードがたくさんだと確信してい__init__を使ってPythonの属性を継承する

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 

class Teenager(Person): 
    def __init__(self, name, phone, website): 
     self.name=name 
     self.phone=phone 
     self.website=website 

(私はJavaで知って、上記のコードのビットのための冗長性がたくさんある):この例を見てみましょう。

親クラスからどの属性がすでに継承されているかに関して、冗長な部分はありますか?

答えて

29

Pythonでクラスに__init__関数を書くときは、常にそのスーパークラスの関数__init__を呼び出す必要があります。他の人が指摘したように

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def __init__(self, name, phone, website): 
     Person.__init__(self, name, phone) 
     self.website=website 

、あなたは

とライン

Person.__init__(self, name, phone) 

を置き換えることができます:私たちは、スーパークラスに直接関連する属性を渡すためにこれを使用することができますので、あなたのコードは次のようになります

super(Teenager, self).__init__(name, phone) 

コードは同じことを行います。これは、Python instance.method(args)Class.method(instance, args)の省略形にすぎないためです。 superを使用する場合は、自分のコードで行ったようにobjectPersonの基本クラスとして指定する必要があります。

python documentationには、superキーワードの使用方法に関する詳細情報があります。この場合に重要なことは、それは彼らがコンストラクタで定義されている場合、PythonでされていないTeenager

+2

Python 2.xを使用している場合、 'super'を使うために' Person'の基本クラスとして 'object'を明示的に指定する必要があることに注意してください。それ以外の場合は、 'Person .__ init__'フォームを使用する必要があります。 – chepner

+0

@chepnerあなたはそれについての参考資料を提供できますか?私は1つを見つけることができません。 – murgatroid99

+0

http://docs.python.org/library/functions.html#superは、super()が新しいスタイルのクラスでのみサポートされていることを示しています。Python 2.xでは 'object'から継承するクラスです。 – chepner

5

属性が継承されず、親クラスのコンストラクタが呼び出されないselfのスーパークラスのメソッド__init__を探すためのpythonを伝えることですその上

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     Person.__init__(self, name, phone) # Call parent class constructor. 
     self.website=website 

よりここに:あなたは、手動でのすべて行う場合を除き、http://docs.python.org/tutorial/classes.html#inheritance

1

__init__を、Javaのコンストラクタとは異なり、自動的に継承階層内のすべてのクラスには呼び出されません - あなたはトンを必要とします自分でやってください。

また、すべてのオブジェクト階層は、特別な場合を除いてobjectに根ざしている必要があります。

あなたのコードは次のようになります。

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     super(Teenager, self).__init__(name, phone) 
     self.website=website 

superは、それぞれの名前(「メソッド解決順序のために呼び出すべき関数のリスト内の次の関数を呼び出します2番目の引数(self)、のためのデリゲートを作成します")。これは、Javaで起こるように、スーパークラスメソッドを呼び出すこととまったく同じではありません。

super(type(self), self).__init__(name, phone)と書くこともできますが、このクラスからさらに継承すると、type(self)Teenagerにならない場合があり、無限の再帰を持つ可能性があります。これは、スーパークラスのコンストラクタを直接呼び出すのではなく、MROの差を持つデリゲートオブジェクトを使用しているという事実の実用的な結果の1つです。

class Teenager(Person): 
     def __init__(self, *args, **kwargs): 
      self.website=kwargs.pop('website') 
      super(Teenager, self).__init__(*args, **kwargs) 

それはこの場合には大きな違いがありませんが、あなたは、引数のトンと__init__を持っている場合、それは楽になります:

11

少しきれいな方法は、私はこれをしたいです。

+0

* argsと** kwargs(多数の引数の場合は効率的)の使用のためにUpvoted。 –

関連する問題