Pythonで関数をオーバーロードしましたか?


91

Pythonで関数をオーバーロードすることは可能ですか?C#では次のようなことをします

void myfunction (int first, string second)
{
//some code
}
void myfunction (int first, string second , float third)
{
//some different code
}

次に、関数を呼び出すと、引数の数に基づいて2つを区別します。Pythonで同様のことを行うことは可能ですか?


これは重複した投稿の可能性があるようです。また、質問はC#とは関係がないため、C#としてフラグを立てないでください。function-overloading-in-python-missing
Jethro 2011


回答:


103

編集Python3.4の新しいシングルディスパッチジェネリック関数については、http: //www.python.org/dev/peps/pep-0443/を参照してください。

通常、Pythonで関数をオーバーロードする必要はありません。Pythonは動的に型指定され、関数へのオプションの引数をサポートします。

def myfunction(first, second, third = None):
    if third is None:
        #just use first and second
    else:
        #use all three

myfunction(1, 2) # third will be None, so enter the 'if' clause
myfunction(3, 4, 5) # third isn't None, it's 5, so enter the 'else' clause

3
ただし、引数のタイプに基づいて異なる関数を呼び出すことははるかに難しいことに注意してください(不可能ではありませんが)。
Andrew Jaffe 2011

9
まあ、オーバーロード/ポリモーフィズムと条件文の間には違いがあります。条件文があるので、多形性は必要ないということですか?
Val

1
@Val基本的に、動的に型指定された言語では、コードで簡単にエミュレートできるため、言語機能としてオーバーロードする必要がなく、そのようにしてポリモーフィズムを取得できると言っています。
agf 2013年

1
@Val Pythonでのオプションの引数と動的型の間では、ポリモーフィズムを実現するためにJavaスタイルのメソッドのオーバーロードは必要ないと言っています。
agf 2013年

3
@navidooそれは良い考えではないと私は主張します-関数は完全に異なるタイプのものを返すべきではありません。ただし、いつでもmain関数内でローカルジェネレーター関数を定義して呼び出し、結果のジェネレーターを返すことができます。外部からは、main関数がジェネレーターである場合と同じになります。ここに例があります。
agf 2014年

50

通常のPythonでは、やりたいことができません。2つの近似値があります。

def myfunction(first, second, *args):
    # args is a tuple of extra arguments

def myfunction(first, second, third=None):
    # third is optional

ただし、本当にこれを実行したい場合は、確実に機能させることができます(伝統主義者を怒らせるリスクがあります; o)。つまり、wrapper(*args)引数とデリゲートの数を適切にチェックする関数を作成します。この種の「ハッキング」は通常、デコレータを介して行われます。この場合、次のようなことができます。

from typing import overload

@overload
def myfunction(first):
    ....

@myfunction.overload
def myfunction(first, second):
    ....

@myfunction.overload
def myfunction(first, second, third):
    ....

これを実装するには、overload(first_fn) 関数(またはコンストラクター)が呼び出し可能なオブジェクトを返すようにします。__call__(*args) メソッドは上記で説明した委任を実行し、overload(another_fn) メソッドは委任可能な関数を追加します。

ここhttp://acooke.org/pytyp/pytyp.spec.dispatch.htmlに似たものの例を見ることができますが、それはタイプごとにメソッドをオーバーロードしています。それは非常によく似たアプローチです...

更新:そして(引数タイプを使用して)同様のものがpython3に追加されています-http ://www.python.org/dev/peps/pep-0443/


range組み込みは、過負荷を使用していますので、それはハック本当にありますか? github.com/python/typeshed/blob/master/stdlib/2and3/...
CptJero

9

はい、可能です。私はPython3.2.1で以下のコードを書きました:

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

使用法:

myfunction=overload(no_arg_func, one_arg_func, two_arg_func)

overload関数によって返されるラムダは、名前のない引数の数に応じて呼び出す関数を選択することに注意してください。

解決策は完璧ではありませんが、現時点ではこれ以上のことは書けません。


1

直接はできません。ただし、指定された引数に対して明示的な型チェックを使用できますが、これは一般的には嫌われています。

Pythonは動的です。オブジェクトで何ができるかわからない場合は、:を試してメソッドを呼び出し、エラーを除いてください。

タイプに基づいてオーバーロードする必要はなく、引数の数だけに基づいてオーバーロードする必要がある場合は、キーワード引数を使用します。


3
彼はオプションの引数について知らなかったと思います。
agf 2011

0

オーバーロードメソッドはPythonでは注意が必要です。ただし、dict、list、またはプリミティブ変数を渡す使用法がある可能性があります。

私は自分のユースケースのために何かを試しました。これは、メソッドをオーバーロードする人々を理解するのに役立つ可能性があります。

stackoverflowスレッドの1つでの使用例を見てみましょう。

異なるクラスからメソッドを呼び出すクラスオーバーロードメソッド。

def add_bullet(sprite=None, start=None, headto=None, spead=None, acceleration=None):

リモートクラスから引数を渡します。

add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},accelaration=10.6}

または add_bullet(sprite = 'test', start=Yes,headto={'lat':10.6666,'long':10.6666},speed=['10','20,'30']}

そのため、メソッドのオーバーロードによるリスト、ディクショナリ、またはプリミティブ変数の処理が行われています。

あなたのコードのためにそれを試してみてください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.