web-dev-qa-db-ja.com

Pythonでメソッドのオーバーロードを使用するにはどうすればよいですか?

私は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)

この作業を行うにはどうすればよいですか?

140
user1335578

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

class A:

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

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

Pythonに同じ名前の2つのメソッドを含めることはできません-する必要はありません。

Pythonチュートリアルの デフォルトの引数値 セクションを参照してください。避けるべき一般的な間違いについては、 "Least Astonishment"およびMutable Default Argument を参照してください。

Edit:Python 3.4の新しい単一ディスパッチジェネリック関数については PEP 44 を参照してください。

135
agf

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'

ご覧のとおり、canを使用すると、単にデフォルト値を持つのではなく、個別の動作をトリガーできます。

>>> ob = A()
>>> ob.stackoverflow()
first form
>>> ob.stackoverflow(2)
second form
46
Chris Morgan

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

編集:Python 3のオーバーロードの公式サポートにより、 @ overload デコレーターを使用できます。

42

あなたはすることはできません。

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

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

def stackoverflow(...): ...を記述すると、メソッドであるオブジェクトを作成し、それをstackoverflowA属性に割り当てます。 2つの定義を記述する場合、2番目の定義が最初の定義を置き換えます。これは、割り当てが常に動作するのと同じ方法です。

さらに、オーバーロードがときどき使用される種類のワイルドなことを行うコードを記述したくありません。それは言語の仕組みではありません。

与えることができるものの種類ごとに個別の関数を定義しようとする代わりに(とにかく関数のパラメーターに型を指定しないため、ほとんど意味がありません)、areそして彼らが何ができるかを考え始めるdo

タプルとリストを処理するために個別に作成できるだけでなく、必要ない、または必要ないもできます。

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

25
Karl Knechtel

Python 3.2.1に答えを書きます。

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

使い方:

  1. overloadは、任意の量の呼び出し可能変数を受け取り、それらをTuple functionsに格納してから、lambdaを返します。
  2. ラムダは任意の数の引数を取り、functions[number_of_unnamed_args_passed]に格納された関数を呼び出した結果を返します。引数はラムダに渡されます。

使用法:

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) \
    )
17
GingerPlusPlus

私はPython 2.7に答えを書きます:

Pythonでは、メソッドのオーバーロードはできません。異なる機能で同じ関数に本当にアクセスしたい場合は、メソッドのオーバーライドをお勧めします。

class Base(): # Base class
    '''def add(self,a,b):
        s=a+b
        print s'''

    def add(self,a,b,c):
        self.a=a
        self.b=b
        self.c=c

        sum =a+b+c
        print sum

class Derived(Base): # Derived class
    def add(self,a,b): # overriding method
        sum=a+b
        print sum



add_fun_1=Base() #instance creation for Base class
add_fun_2=Derived()#instance creation for Derived class

add_fun_1.add(4,2,5) # function with 3 arguments
add_fun_2.add(4,2)   # function with 2 arguments
13
Moorthi Muthu

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

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

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

13
mayhewr

Pythonでは、オーバーロードは適用された概念ではありません。ただし、たとえば、foo型の引数と、bar型の引数に別の初期化子を渡した場合、1つの初期化子を実行する場合を作成する場合は、Pythonオブジェクトとして処理される場合、渡されたオブジェクトのクラスタイプの名前を確認し、それに基づいて条件付き処理を記述できます。

class A:
   def __init__(self, arg)
      # Get the Argument's class type as a String
      argClass = arg.__class__.__name__

      if argClass == 'foo':
         print 'Arg is of type "foo"'
         ...
      Elif argClass == 'bar':
         print 'Arg is of type "bar"'
         ...
      else
         print 'Arg is of a different type'
         ...

この概念は、必要に応じて異なる方法で複数の異なるシナリオに適用できます。

9
S. Gamgee

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

class A:

    def stackoverflow(self, i=None):    
        if i == None:
            print 'first method'
        else:
            print 'second method',i
7
John Gaines Jr.

ちょうどこれに出くわした https://github.com/bintoro/overloading.py 興味のある人なら誰でも。

リンクされたリポジトリのreadmeから:

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

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

特徴

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

5
Mark Lawrence

@agfは PEP-3124 で過去の答えに正しかったのですが、構文がわかりました。 @overloadデコレータの 詳細についてはドキュメントの入力 を参照してください。ただし、これは実際には単なる構文暗示であり、IMHOはこれまで議論されてきたすべてです。個人的には、異なるシグネチャを持つ複数の関数を使用すると読みやすくなり、20以上の引数を持つすべての関数がデフォルト値(ほとんどの場合None)に設定され、その後無限のifElifelsechainsを使用していじる必要があります呼び出し元が提供された引数のセットを使用して関数に実際に何をさせたいかを調べます。これ、Python Zenに続いて長い間延期されました

いよりも美しいほうがいい。

そしてほぼ間違いなく

単純なものは複雑なものよりも優れています。

上記の公式Pythonドキュメントから直接:

@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>
3
masi

Pythonは、JavaやC++などのメソッドのオーバーロードをサポートしていません。メソッドをオーバーロードする場合がありますが、使用できるのは最新の定義済みメソッドのみです。

# First sum method.
# Takes two argument and print their sum
def sum(a, b):
    s = a + b
    print(s)

# Second sum method
# Takes three argument and print their sum
def sum(a, b, c):
    s = a + b + c
    print(s)

# Uncommenting the below line shows an error    
# sum(4, 5)

# This line will call the second sum method
sum(4, 5, 5)

呼び出し時に異なる数の引数を提供するために、オプションの引数または* argsを提供する必要があります。

https://www.geeksforgeeks.org/python-method-overloading/ からの礼儀

3
Atihska

Python 3.xには、@ overloadデコレータを使用してメソッドのオーバーロードを可能にする標準型付けライブラリが含まれています。残念ながら、これはコードを読みやすくするためです。@ overload装飾メソッドの後には、異なる引数を処理する非装飾メソッドが続く必要があるためです。詳細はここにあります here しかしあなたの例では:

from typing import overload
from typing import Any, Optional
class A(object):
    @overload
    def stackoverflow(self) -> None:    
        print('first method')
    @overload
    def stackoverflow(self, i: Any) -> None:
        print('second method', i)
    def stackoverflow(self, i: Optional[Any] = None) -> None:
        if not i:
            print('first method')
        else:
            print('second method', i)

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

MathMethod.pyファイル内

from multipledispatch import dispatch
@dispatch(int,int)
def Add(a,b):
   return a+b 
@dispatch(int,int,int)  
def Add(a,b,c):
   return a+b+c 
@dispatch(int,int,int,int)    
def Add(a,b,c,d):
   return a+b+c+d

Main.pyファイル

import MathMethod as MM 
print(MM.Add(200,1000,1000,200))

Multipledispatchを使用してメソッドをオーバーロードできます

0
Mahabubuzzaman