私はJava 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の場合、上記のコードには多くの冗長性があることを知っています)。
どの属性が親クラスから既に継承されているかに関して、どの部分が冗長ですか?
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
を使用する場合は、コードで行ったように、object
の基本クラスとしてPerson
を指定します。
python documentation には、super
キーワードの使用方法に関する詳細があります。この場合の重要なことは、self
ではないTeenager
のスーパークラスで___init__
_メソッドを探すようにpythonに指示することです。
私がこれをしたいのは少しきれいな方法です:
class Teenager(Person):
def __init__(self, *args, **kwargs):
self.website=kwargs.pop('website')
super(Teenager, self).__init__(*args, **kwargs)
この場合、大きな違いはありませんが、__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
これまでの例はすべて、Python 2.xに対するものでしたが、ここではPython 3.xのsuper )およびオブジェクトから継承しません。
class Person:
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Teenager(Person):
def __init__(self, name, phone, website):
super().__init__(name, phone)
self.website = website
___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つの実用的な結果です。