0

編集:私はPython 3を使用しています(何人かが尋ねました)。

これは単なる構文の問題だと思いますが、不足しているものがないことを確認したいと思います。Foo と Bar の実装方法の構文の違いに注意してください。彼らは同じことを達成しており、私は彼らが本当に同じことをしていることを確認したいと思っています. 出力は、同じことを行う方法が 2 つしかないことを示しています。そうですか?

コード:

class X:

    def some_method(self):
        print("X.some_method called")

class Y:

    def some_method(self):
        print("Y.some_method called")

class Foo(X,Y):

    def some_method(self):
        X().some_method()
        Y().some_method()
        print("Foo.some_method called")

class Bar(X,Y):

    def some_method(self):
        X.some_method(self)
        Y.some_method(self)
        print("Bar.some_method called")

print("=== Fun with Foo ===")
foo_instance = Foo()
foo_instance.some_method()

print("=== Fun with Bar ===")
bar_instance = Bar()
bar_instance.some_method()

出力:

=== Fun with Foo ===
X.some_method called
Y.some_method called
Foo.some_method called
=== Fun with Bar ===
X.some_method called
Y.some_method called
Bar.some_method called

PS - 言うまでもありませんが、これは単なる抽象的な例です。両方の祖先でsome_method を呼び出す理由について心配する必要はありません。ここでは、言語の構文とメカニズムを理解しようとしています。皆さんありがとう!

4

2 に答える 2

3
  1. 新しいスタイルのクラスを使用する必要があります。これが Python 3 の場合は、次のようになります。Python 2 を使用している場合は、object(または他の新しいスタイルのクラス) から継承する必要があります。
  2. 祖先メソッドを呼び出す通常の方法は、super. それについては、標準ドキュメントと、それがどのように動作するかについての他の優れた記事を読んでください。あなたが行っている方法でメソッドを呼び出すことは決して推奨されません。(a) さらなる継承に直面すると脆弱になるからです。(b) クラスへの参照をハードコーディングすることで、メンテナンスの労力を増やします。

super更新:これを実現するための使用方法を示す例を次に示します: http://ideone.com/u3si2

こちらもご覧ください: http://rhettinger.wordpress.com/2011/05/26/super-considered-super/

更新 2:現在の名前のハードコーディングを避けるために、すべてのメソッドに__class__変数と引数なしを追加する Python 2 用の小さなライブラリがあります: https://github.com/marcintustin/superfixersuper

于 2012-09-05T02:26:01.017 に答える
2

それらは同じではありません。 X()class のオブジェクトを作成しますX。その場合はX().someMethod()、新しいオブジェクトを作成してから、 ではなくそのオブジェクトでメソッドを呼び出しますselfX.someMethod(self)これは、同じオブジェクトで継承されたメソッドを呼び出すためです。

selfメソッドが実際にオブジェクトに対して何かを行う場合、違いがわかります。たとえばself.blah = 8、メソッドに入れるX.someMethod(self)と、呼び出したオブジェクトの後にblah属性が設定されますが、その後は設定されX().someMethod()ません。(代わりに、新しいオブジェクトを作成し、blahそれに設定し、その新しいオブジェクトを使用せずに破棄し、元のオブジェクトをそのままにします。)

コードを変更する簡単な例を次に示します。

>>> class X:
... 
...     def some_method(self):
...         print("X.some_method called on", self)
... 
... class Y:
... 
...     def some_method(self):
...         print("Y.some_method called on", self)
... 
... class Foo(X,Y):
... 
...     def some_method(self):
...         X().some_method()
...         Y().some_method()
...         print("Foo.some_method called on", self)
... 
... class Bar(X,Y):
... 
...     def some_method(self):
...         X.some_method(self)
...         Y.some_method(self)
...         print("Bar.some_method called on", self)
>>> Foo().some_method()
('X.some_method called on', <__main__.X instance at 0x0142F3C8>)
('Y.some_method called on', <__main__.Y instance at 0x0142F3C8>)
('Foo.some_method called on', <__main__.Foo instance at 0x0142F3A0>)
>>> Bar().some_method()
('X.some_method called on', <__main__.Bar instance at 0x0142F3C8>)
('Y.some_method called on', <__main__.Bar instance at 0x0142F3C8>)
('Bar.some_method called on', <__main__.Bar instance at 0x0142F3C8>)

Fooを使用すると、印刷されるオブジェクトが同じではないことに注意してください。1 つは X インスタンス、1 つは Y インスタンス、最後はメソッドを呼び出した元の Foo インスタンスです。を使用するBarと、各メソッド呼び出しで同じオブジェクトになります。

(super場合によっては、基底クラスに明示的に名前を付けるのを避けるために を使用することもできます。たとえば、Python super(Foo, self).someMethod()3 ではsuper().someMethod().super一般に、各メソッドが 1 回だけ呼び出さsuperれ、継承チェーン内のメソッドの次のバージョンに制御が渡され、その次のバージョンに制御が渡されるなどの場合を対象としています)。

于 2012-09-05T02:17:47.123 に答える