web-dev-qa-db-ja.com

Python言語には何種類の多型がありますか?

私は Luca Cardelli による記事を読んだだけで、彼は次のような多型のタイプを説明しました:

記事の名前は タイプ、データの抽象化、および多態性について です。

多型の種類

Cardelliは、この記事でいくつかのタイプの多態性を定義しています。

  • ユニバーサル
    • パラメトリック
    • 包含
  • このために
    • オーバーロード
    • 強制

また、ポリモーフィズムは大きく2種類しかないという理論もあります。

  • ランタイムポリモーフィズム
  • コンパイル時のポリモーフィズム

だから私は少し混乱しています。私はOOP in pythonと読んでいる間pythonは動的型言語なので、私はpythonエキスパートは、Pythonで使用されているポリモーフィズムのタイプについて説明してください。

3
Pythonist

あなたが発見したように、ポリモーフィズムの多くの異なる定義があります。この回答は実用的な観点から対処するものであり、学術的な定義と一致しない場合があります。

サブタイプのポリモーフィズム(継承による)

これは、ポリモーフィズムという用語に関してほとんどの人が考えていると思われる一種のポリモーフィズムです。ここで、メソッドがサブクラスによって継承され、オーバーライドできます。例(Python 2.7):

class Foo(object):
  def test(self):
    print self.name()

  def name(self):
    return "Foo"

class Bar(Foo):
  def name(self):
    return "Bar"

foo = Foo()
bar = Bar()

print type(foo)
print type(bar)

print isinstance(bar, type(foo))

Foo().test()
Bar().test()

出力:

<class '__main__.Foo'>
<class '__main__.Bar'>
True
Foo
Bar

これは、JavaまたはC#のサブタイプのポリモーフィズムと同じように機能します。

アヒルのタイピング

Pythonには、ダックタイピングと呼ばれる機能もあります。技術的には、サブタイプと継承を区別する場合、これはサブタイプの継承でもあります(Pythonについて考えるのに正しい方法だと思います)。この用語は慣用句から来ています。「アヒルのように見え、アヒルのように鳴く場合、おそらくそれは「アヒル」ですが、「アヒルのように鳴く場合」に短縮されることがよくあります。これが同じ問題を解決するために使用できるので、これが学術文献の多型であるかどうかはあまり重要ではないと主張します:

class Foo(object):
  def test(self):
    print "Foo"

class Bar(object):
  def test(self):
    print "Bar"

foo = Foo()
bar = Bar()

print type(foo)
print type(bar)

print isinstance(bar, type(foo))

Foo().test()
Bar().test()

出力:

<class '__main__.Foo'>
<class '__main__.Bar'>
False
Foo
Bar

ご覧のように、以前と同じような動作をすることができますが、今度はBarはFooではありません。ダックタイピングは、サブタイピングが行われないPythonプログラムで非常に一般的に使用されています。たとえば、listの操作のすべて(実際にはほとんど)が実装され、純粋なメソッドからでもis as listのようにメソッドに渡されるリストのようなオブジェクトを作成することは一般的ですタイピングの観点から、それは実際にはリストから派生したタイプではありません。

パラメトリック多態性

私は、これをJavaまたはC#のジェネリックスのようなものと解釈します。これはPythonに関係があるとは思わないが、Pythonについてはスピードが出ない。

メソッドのオーバーロード

これは興味深いケースです。純粋なPythonの観点からは、メソッドをオーバーロードできないため、これは意味がありません。つまり、同じメソッド名を2回定義することはできません。興味深いのは、Jython(JVMで実行するようにコンパイルされるPython)では、JavaもPythonも持たない機能、つまりダブルディスパッチを取得することです。オーバーロードされたJavaメソッドのどのバージョンをpythonステートメントから呼び出すかを決定するとき、ランタイムは呼び出しのパラメーターの実際のタイプを調べ、バージョンを動的に選択します。 Javaでは、オーバーロードされたメソッドはコンパイル時に呼び出しにバインドされますが、これは技術的に多態的ですが、実際には興味深い方法ではありません。二重ディスパッチオーバーロードは、いくつかの興味深い効果を実装するために実際に使用できます。これはIronPythonでも同様に機能し、C#ライブラリを呼び出すと予想されます。

私はここでベースのほとんどをカバーしたと思います。ポリモーフィックと見なされる可能性がある追加機能については、コメントを歓迎します。よくわからないことの1つは、__getattr__または__setattr__などを使用して合成または仮想のプロパティ/メソッドを作成する機能です。また、メソッド参照を渡すことはポリモーフィズムの一種であるという主張もできると思いますが、多分それは少し伸びすぎているかもしれません。

5
JimmyJames

まだ記事は読んでいませんが、これを試してみましょう。

Pythonは動的に型付けされた言語です。学者がタイプについて話すとき、彼らは特に明記しない限り静的にタイプされた言語について話している。動的型付けと静的型付けは同じ目標の多くを共有しますが、これらの目標を達成する方法は大幅に異なります。

これはここに当てはまります。 Python具体的にはduck-typingを使用します。これは、canが実行されるすべての操作、-willが実行されることを意味します。

詳しく説明すると、これは、オブジェクトafooメソッドがある場合、式a.fooは成功することを意味します実際のaに関係なく =。パラメトリックおよびサブタイプのポリモーフィズムは、アヒルのタイピングのコンテキストでは無意味です。

Pythonはいくつかの一般的なcoercion演算子をサポートしています。それらの完全なリストはわかりませんが、たとえば、整数5 + 1.2は浮動小数点数5に強制変換されるため、式5.0は有効です。

Pythonでは、関数のオーバーロードによるアドホックなポリモーフィズムは不可能です。

私はまた、いくつかの理論では、多型には広く2種類しかないと述べています。

これは多態性の分類ではありません。これは、別の名前による動的型付けと静的型付けです。動的型付けは実行時の多態性(存在する場合)を使用し、静的型付けはコンパイル時の多態性を使用します。

1
gardenhead