210

Pythonでメソッドのオーバーロードを実装しようとしています:

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow(2)

しかし、出力は次のとおりですsecond method 2。同様に:

class A:
    def stackoverflow(self):    
        print 'first method'
    def stackoverflow(self, i):
        print 'second method', i

ob=A()
ob.stackoverflow()

与える

Traceback (most recent call last):
  File "my.py", line 9, in <module>
    ob.stackoverflow()
TypeError: stackoverflow() takes exactly 2 arguments (1 given)

どうすればこれを機能させることができますか?

4

15 に答える 15

167

メソッドのオーバーライドではなく、メソッドのオーバーロードです。Python では、これらすべてを 1 つの関数で行います。

class A:

    def stackoverflow(self, i='some_default_value'):
        print 'only method'

ob=A()
ob.stackoverflow(2)
ob.stackoverflow()

Python では、同じ名前のメソッドを 2 つ持つことはできません。また、その必要もありません。

Python チュートリアルの「既定の引数値」セクションを参照してください。避けるべきよくある間違いについては、「最小の驚き」と変更可能なデフォルト引数を参照してください。

Python 3.4 の新しいシングル ディスパッチ ジェネリック関数については、PEP 443を参照してください。

于 2012-04-18T04:53:05.673 に答える
89

pythonlangutilを使用することもできます:

from pythonlangutil.overload import Overload, signature

class A:
    @Overload
    @signature()
    def stackoverflow(self):    
        print 'first method'

    @stackoverflow.overload
    @signature("int")
    def stackoverflow(self, i):
        print 'second method', i
于 2015-04-26T12:11:53.100 に答える
50

Python では、そのようにはしません。Java のような言語でこれを行う場合、通常はデフォルト値が必要です (そうでない場合は、通常、別の名前のメソッドが必要です)。そのため、Python ではデフォルト値を設定できます

class A(object):  # Remember the ``object`` bit when working in Python 2.x

    def stackoverflow(self, i=None):
        if i is None:
            print 'first form'
        else:
            print 'second form'

ご覧のとおり、これを使用して、単にデフォルト値を設定するのではなく、別の動作をトリガーできます。

>>> ob = A()
>>> ob.stackoverflow()
first form
>>> ob.stackoverflow(2)
second form
于 2012-04-18T04:55:24.180 に答える
49

agfは過去 3.4 より前の答えで正しかったのですが、現在はPEP-3124でシンタックス シュガーを手に入れました。

デコレータの詳細については、型付けに関するドキュメントを参照してください。@overload

個人的には、異なるシグネチャを持つ複数の関数を使用すると読みやすくなり、20 個以上の引数がすべてデフォルト値に設定された単一の関数を使用し (Noneほとんどの場合)、エンドレスif, elif,elseチェーンを使用して見つける必要があることに同意します。呼び出し元が実際に、提供された引数のセットを使用して関数に実行させたいこと。これは、Python Zen に続いて長い間延期されていました。

美しいことは醜いことよりも優れています。

そして間違いなくまた

シンプルは複雑よりも優れています。

上にリンクされている公式の Python ドキュメントから直接:

from typing import overload
@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> Tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    <actual implementation>

編集: 他の言語の場合、この例が期待どおりに機能しない理由を知りたい人は、このディスカッションを参照することをお勧めします。関数には実際の@overloaded実装は想定されていません。これは、Python ドキュメントの例からは明らかではありません。

于 2018-09-23T16:27:48.057 に答える
24

あなたはできません、決してする必要はありませんし、本当にしたくありません。

Pythonでは、すべてがオブジェクトです。クラスは物なので、オブジェクトです。メソッドもそうです。

Aクラスであるというオブジェクトがあります。と呼ばれる属性がありますstackoverflow。そのような属性は1つだけ持つことができます。

を書くdef stackoverflow(...): ...と、メソッドであるオブジェクトを作成し、それをのstackoverflow属性に割り当てますA。2つの定義を作成すると、割り当てが常に動作するのと同じように、2番目の定義が最初の定義に置き換わります。

さらに、オーバーロードが時々使用されるような種類のワイルドなことを行うコードを書きたくありません。それは言語がどのように機能するかではありません。

与えられる可能性のあるもののタイプごとに個別の関数を定義しようとする代わりに(とにかく関数パラメーターのタイプを指定しないのでほとんど意味がありません)、物事何であるかを心配するのをやめて、それらが何ができるかを考え始めます

タプルとリストを処理するために別のタプルを作成できないだけでなく、必要がない、または作成する必要もありません

あなたがすることは、それらが両方とも、例えば、反復可能であるという事実を利用することです(つまり、あなたは書くことができますfor element in container:)。(それらが継承によって直接関連していないという事実は関係ありません。)

于 2012-04-18T06:24:51.587 に答える
17

あなたが探している言葉は「過負荷」だと思います。Python にはメソッドのオーバーロードはありません。ただし、次のようにデフォルトの引数を使用できます。

def stackoverflow(self, i=None):
    if i != None:
        print 'second method', i
    else:
        print 'first method'

引数を渡すと、最初の条件のロジックに従い、最初の print ステートメントを実行します。引数を渡さないと、else条件に入り、2 番目のprintステートメントが実行されます。

于 2012-04-18T04:54:54.577 に答える
15

私はPython 3.2.1で答えを書いています。

def overload(*functions):
    return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)

使い方:

  1. overload任意の量の callable を取り、それらを tuplefunctionsに格納してから、ラムダを返します。
  2. functions[number_of_unnamed_args_passed]ラムダは任意の数の引数を取り、ラムダに渡された引数を使用して、called に格納されている呼び出し関数の結果を返します。

使用法:

class A:
    stackoverflow=overload(                    \
        None, \ 
        #there is always a self argument, so this should never get called
        lambda self: print('First method'),      \
        lambda self, i: print('Second method', i) \
    )
于 2014-10-24T19:07:46.837 に答える
7

Python では、デフォルトの引数を使用してこれを行います。

class A:

    def stackoverflow(self, i=None):    
        if i == None:
            print 'first method'
        else:
            print 'second method',i
于 2012-04-18T04:55:29.240 に答える
5

興味のある人のために、 overloading.py (Python 3 の関数オーバーロード) に出くわしました。

リンクされたリポジトリの README ファイルから:

オーバーロードは、ランタイム引数の型と数に基づいて関数ディスパッチを提供するモジュールです。

オーバーロードされた関数が呼び出されると、ディスパッチャーは提供された引数を使用可能な関数シグネチャと比較し、最も正確に一致する実装を呼び出します。

特徴

登録時の機能検証と詳細な解決ルールにより、実行時に明確に定義された固有の結果が保証されます。優れたパフォーマンスのために関数解決キャッシュを実装します。関数シグネチャでオプションのパラメーター (デフォルト値) をサポートします。最適な一致を解決するときに、位置引数とキーワード引数の両方を評価します。フォールバック機能と共有コードの実行をサポートします。引数のポリモーフィズムをサポートします。classmethods と staticmethods を含む、クラスと継承をサポートします。

于 2015-02-06T20:51:53.783 に答える