web-dev-qa-db-ja.com

Pythonでオブジェクトの__init __()メソッドは何をしますか?

OpenStackのコードを読んでいるときに、これに遭遇しました。

「Service」という名前のクラスは、基本クラス「object」を継承し、Serviceの__init__()メソッドで、オブジェクトの___init___が呼び出されます。関連するコードは次のようになります。

クラス定義:

_class Service(object):
_

およびサービスのinitメソッド定義:

_def __init__(self, Host, binary, topic, manager, report_interval=None,
             periodic_interval=None, *args, **kwargs):
_

そして、サービスのinitでsuper(ここでは「オブジェクト」)を呼び出します。

_super(Service, self).__init__(*args, **kwargs)
_

私は最後の呼び出しを理解していません、object.__init__()実際に何をしていますか?誰か助けてもらえますか?

22
can.

短い答えは、object .__ init __()メソッドは、引数が渡されていないことを確認する以外は何もしないということです。詳細は source を参照してください。

Serviceのインスタンスで呼び出されると、super()呼び出しはobject .__ init __()に委任され、何も起こりません。

ただし、Serviceのサブクラスのインスタンスで呼び出されると、物事はさらに面白くなります。 super()呼び出しは、object以外のクラスにデリゲートする可能性があります、インスタンスの親であるがServiceの親ではないクラス。これがどのように機能するか、そしてなぜそれが有用であるかについての詳細は、ブログの投稿 Pythonのスーパー考慮スーパー !を参照してください。

次の例(やや工夫)は、ServiceのサブクラスがsuperServiceを呼び出して、Colorという別のクラスに転送します:

class Service(object):
    def __init__(self, Host, binary, topic, manager, report_interval=None,
             periodic_interval=None, *args, **kwargs):
        print 'Initializing Service'
        super(Service, self).__init__(*args, **kwargs)

class Color(object):
    def __init__(self, color='red', **kwargs):
        print 'Initializing Color'
        self.color = color
        super(Color, self).__init__(**kwargs)

class ColoredService(Service, Color):
    def __init__(self, *args, **kwds):
        print 'Initializing Colored Service'
        super(ColoredService, self).__init__(*args, **kwds)

c = ColoredService('Host', 'bin', 'top', 'mgr', 'ivl', color='blue')

この例では、初期化は次の順序で行われます。

  1. カラーサービスの初期化
  2. サービスの初期化
  3. 色の初期化
  4. オブジェクトの初期化-引数の確認以外は何もしません
15

super()は常に親クラスのプロキシを返すわけではありません。代わりに、のプロキシを返します [〜#〜] mro [〜#〜]の次のクラス単一継承では、MROと継承チェーンの間に違いはありません。多重継承では、MROは代わりにother継承チェーン上のクラスになる可能性があります。

object.__init__()は実際には何もしませんが、クラスがobjectだけをスーパークラスとして持っている場合でも、super()呼び出しを含める必要があります。

「スーパー」の大きな問題の1つは、スーパークラスのメソッドのコピーが呼び出されるように見えることです。これは単にそうではなく、MROの次のメソッドが呼び出される原因になります(...)super(...)への呼び出しが省略されます。initスーパークラスが「オブジェクト」の場合結局のところ、object .initは何もしません!ただし、これは非常に間違っています。これを行うと、他のクラスのinitメソッドが呼び出されなくなります。

http://fuhm.net/super-harmful/

1
Eduardo Ivanec