파이썬에서 메소드 오버로딩을 어떻게 사용합니까?


169

파이썬에서 메소드 오버로드를 구현하려고합니다.

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)

이 작업을 어떻게합니까?


39
파이썬에서는 메소드를 특수한 " 속성 " 세트로 생각 하면 객체에 대해 주어진 이름의 하나의 " 속성 "(따라서 하나의 메소드) 만있을 수 있습니다 . 마지막 방법 은 이전 방법을 덮어 씁니다 . Java에서 메소드는 일류 시민이 아니며 ( "객체의 속성"이 아님) 가장 가까운 유형 ( 오버로드발생 하는 위치)에 따라 정적으로 해결되는 "메시지 전송"에 의해 호출됩니다 .



6
왜이 질문에 대한 답이 아직 받아 들여지지 않습니까? 가장 좋아하는 답변의 왼쪽에있는 체크 표시를 클릭하십시오.
glglgl

답변:


150

그것은의 메소드 오버로딩은 방법이 아니다 오버라이드 (override) . 그리고 파이썬에서는 하나의 함수로 모든 것을 수행합니다.

class A:

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

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

파이썬에서 같은 이름을 가진 두 개의 메소드를 가질 수 없으며 필요하지 않습니다.

Python 튜토리얼 의 기본 인수 값 섹션을 참조하십시오 . 피해야 할 일반적인 실수 는 "최소한의 놀라움"과 가변성 기본 인수 를 참조하십시오 .

편집 : Python 3.4의 새로운 단일 디스패치 일반 함수에 대한 정보는 PEP 443 을 참조하십시오 .


119
당신은 할 필요가 없습니다 ++ 언젠가이 방법은 C에서 예를 들어 같은 과부하가 매우 편리 할 것입니다 IMHO -. 좋아, 그것은 다른 구조를 사용하여 수행 할 수 없다는 의미에서 '필요하지'않지만 어떤 것이 더 쉽고 간단 해집니다.
Andreas Florath

7
@AndreasFlorath 동의하지 않습니다. 오리 타이핑을 좋아하고 각 방법을 작성하여 한 가지만 수행하는 방법을 배우고 방법 오버로드가 필요하지 않습니다.
agf

4
잡히기 전에 "피해야 할 일반적인 실수"에 대해 +1
mdup

43
오버로드는 종종 코드를 더 깨끗하게 만듭니다. 여러 경우를 처리하기에는 너무 많은 if-else 문으로 메소드를 압축하지 않기 때문입니다. 어떤 의미에서 기능 언어의 전체 영역은 비슷한 아이디어, 즉 인수 패턴 일치를 사용합니다. 즉, 읽을 수없는 거대한 방법보다는 더 작은 방법을 사용하게됩니다.
sten

2
@ user1019129 파이썬 3.4에 추가되고 내 답변에 링크 된 단일 디스패치 일반 함수의 목적입니다.
agf

62

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

6
나는 이것이 그 질문에 대한 유일한 유효한 대답이라고 생각합니다. 내가 할 수 있다면 나는 두 배로 찬성 할 것이다.
Michael

3
그것은 좋지만 원시 함수에서는 작동하지 않으며 클래스 내의 메소드에서만 작동합니다.
Legit Stack

1
@LegitStack이 기능도 추가 할 수 있습니다. 불가능하지 않습니다.
Ehsan Keshavarzian

3
@LegitStack GitHub의 코드를 업데이트했지만 이제는 함수와 함께 작동합니다.
Ehsan Keshavarzian '08

1
@PaulPrice 맞습니다. 답변을 업데이트하고 공식 지원 섹션을 삭제했습니다. 여전히 내 코드를 사용하여 과부하를 전달할 수 있습니다. 이제는 메소드와 함수 모두에서 작동합니다. GitHub에서 코드를 가져옵니다. 아직 PyPi를 업데이트하지 않았습니다.
Ehsan Keshavarzian

48

파이썬에서는 그런 식으로 일을하지 않습니다. 사람들이 Java와 같은 언어로 그렇게 할 때 일반적으로 기본값을 원합니다 (그렇지 않으면 일반적으로 다른 이름을 가진 메소드를 원합니다). 따라서 파이썬에서는 기본값을 가질 수 있습니다 .

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

2
None변경 가능한 기본값을 원할 때 주로 유용합니다. 별도의 동작은 별도의 기능에 있어야합니다.
agf

@agf : None또한 기본값으로 사용할 수 있습니다.
Chris Morgan

그렇습니다. 그러나 나는 그것을 센티넬 값으로 사용하는 것에 대해 언급했습니다.
agf

"일반적으로"라고합니까? 이것이 항상 그런 것은 아니라는 것을 의미합니까?
joel

24

당신은 할 필요가 없으며, 정말로 필요하지도 않습니다.

파이썬에서는 모든 것이 객체입니다. 클래스는 사물이므로 객체입니다. 방법도 있습니다.

A클래스 라는 개체가 있습니다 . 라는 속성이 stackoverflow있습니다. 그러한 속성은 하나만 가질 수 있습니다.

을 쓸 때 def stackoverflow(...): ...발생하는 것은 메소드 인 객체를 생성하여 stackoverflow속성에 할당하는 것입니다 A. 두 개의 정의를 작성하면 두 번째 정의가 첫 번째 정의를 대체하며 할당은 항상 동작하는 방식과 동일합니다.

또한 오버로딩이 때때로 사용되는 더 많은 종류의 작업을 수행하는 코드를 작성하고 싶지 않습니다. 언어가 작동하는 방식이 아닙니다.

대신, (어쨌든 함수 매개 변수 유형을 지정하지 않기 때문에 거의 의미)이 제공 될 수있는 것은 각 유형에 대해 별도의 함수를 정의하기 위해 노력 정지 일들이 무엇인지에 대한 걱정 이다 그들이 할 수 있는지에 대해 생각하기 시작 수행하십시오 .

튜플 대 목록을 처리하기 위해 별도의 것을 작성할 수있을뿐만 아니라 원하지 않거나 필요하지도 않습니다 .

당신이하는 일은 둘 다 반복 가능하다는 것 (즉, 쓸 수 있음 for element in container:)을 활용하는 것입니다. (그들이 상속과 직접 관련이 없다는 사실은 관련이 없습니다.)


6
TBH, 나는 "필요하지 않다"고 더 조심할 것입니다. 이것은 실제 세계의 모든 기능과 완전한 프로그래밍 언어에 태그를 지정할 수있는 것이므로 유효한 주장이 아닙니다. 누가 발전기 가 필요 합니까? 누가 수업이 필요 합니까? 프로그래밍 언어는 구문적인 설탕 일뿐입니다.
Sebastian Mach

6
완전히 동의하지 않습니다. "필요하지 않은"또는 "원치 않는"일 수도 있지만 필사적으로 원하는 응용 프로그램이 충분합니다. 예를 들어 instanceof 's로 프로그램을 어지럽히 지 않고 파이썬과 numpy 배열을 모두 처리하는 프로그램을 작성해보십시오.
Elmar Zander

1
masi의 답변을 바탕으로, "당신이 할 수 없습니다"는 이제 부정확하고 쓸모가 없다고 말하고 싶습니다. @overload데코레이터 의 존재에 기초하여, "실제로 원하지 않는다"는 논쟁의 여지가 있다고 말하고 싶습니다. PEP-3124에서 "... 현재 파이썬 코드가 수신 한 인수의 유형을 검사하는 일반적인 안티 패턴입니다 ...이 작업을 수행하는 '분명한 방법'은 유형 검사에 의한 것입니다. extension ... "그래서 충분한 사람들이 원하는 것처럼 보이고 파이썬의 일부가되었습니다.
Mike S

@MikeS 표준 @overload은 입력 전용입니다.
Narfanar

@Narfanar 귀하의 답변이 내 의견에 어떻게 적용되는지 모르겠습니다. 설명해 주시겠습니까?
Mike S

16

@agf가 PEP-3124로 과거의 대답에 옳았지만 구문 설탕을 얻었습니다. 데코레이터 에 대한 자세한 내용타이핑 설명서를 참조하십시오. @overload이것은 실제로 구문 설탕이며 IMHO는 그 이후로 사람들이 논쟁 해 온 모든 것입니다. 개인적으로 나는 다른 서명 여러 기능을 가지는 것은 다음 20 개 이상의 인수를 기본 값으로 모든 설정 (단일 기능을 갖는 더 쉽게 읽을 동의 None끝없는 사용하여 주변에 바이올린을 가진 후 대부분의 시간) 및 if, elif, else알아 체인 무엇 호출자는 실제로 함수가 제공된 인수 세트와 관련되기를 원합니다. 이것은 파이썬 선을 따라 오랜 시간이 지났습니다

못생긴 것보다 아름답습니다.

그리고 틀림없이

단순보다 복잡합니다.

위에 링크 된 공식 파이썬 문서에서 직접 :

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>

내가 찾던 것, 자신의 오버로드 데코레이터를 정의하는 것보다 깔끔한
pcko1

2
btw : 이것이 왜 작동하지 않는지 궁금한 사람은 stackoverflow.com/questions/52034771/… 의 토론을 살펴 보는 것이 좋습니다 . @overloaded 함수에는 실제 구현이 없어야합니다. 이것은 파이썬 문서의 예제에서 분명하지 않습니다.
masi

15

파이썬 3.2.1로 답을 씁니다.

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

작동 방식 :

  1. overload호출 가능한 양을 가져와 tuple에 저장 functions한 다음 람다를 반환합니다.
  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) \
    )

14

찾고있는 단어가 "오버로딩"이라고 생각합니다. 파이썬에서는 메소드 오버로드가 없습니다. 그러나 다음과 같이 기본 인수를 사용할 수 있습니다.

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

인수를 전달하면 첫 번째 조건의 논리를 따르고 첫 번째 print 문을 실행합니다. 인수를 전달하지 않으면 else조건으로 이동 하여 두 번째 print 문을 실행합니다.


13

파이썬 2.7로 답을 씁니다.

파이썬에서는 메소드 오버로딩이 불가능합니다. 다른 기능으로 동일한 기능에 액세스하려면 메서드 재정의를 수행하는 것이 좋습니다.

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

9

파이썬에서 오버로드는 적용되는 개념이 아닙니다. 그러나 예를 들어 유형의 인수를 전달하면 하나의 이니셜 라이저를 수행 foo하고 유형의 인수는 다른 이니셜 라이저를 수행하려는 경우 barPython의 모든 것이 객체로 처리되므로 검사 할 수 있습니다 전달 된 객체의 클래스 유형 이름 및이를 기반으로하는 조건부 처리

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'
         ...

이 개념은 필요에 따라 다른 방법을 통해 여러 시나리오에 적용될 수 있습니다.


7

파이썬에서는 기본 인수 로이 작업을 수행합니다.

class A:

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

5

관심있는 사람을 위해이 https://github.com/bintoro/overloading.py 를 발견했습니다 .

링크 된 저장소의 readme에서 :

오버로드는 런타임 인수의 유형과 수에 따라 함수 디스패치를 ​​제공하는 모듈입니다.

오버로드 된 함수가 호출되면 디스패처는 제공된 인수를 사용 가능한 함수 서명과 비교하고 가장 정확한 일치를 제공하는 구현을 호출합니다.

풍모

등록시 기능 검증 및 자세한 해결 규칙은 런타임시 고유하고 명확한 결과를 보장합니다. 뛰어난 성능을 위해 함수 해상도 캐싱을 구현합니다. 함수 시그니처에서 선택적 매개 변수 (기본값)를 지원합니다. 최상의 일치를 해결할 때 위치 및 키워드 인수를 모두 평가합니다. 대체 기능 및 공유 코드 실행을 지원합니다. 인수 다형성을 지원합니다. 클래스 메소드 및 정적 메소드를 포함하여 클래스 및 상속을 지원합니다.


3

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/


과부하가 아닙니다. 덮어 쓰기라고합니다. 후자는 Python에서 지원됩니다. 첫 번째는 데코레이터로 구현할 수 있습니다.
Paebbels

2

Python 3.x에는 @overload 데코레이터를 사용하여 메서드 오버로드를 허용하는 표준 타이핑 라이브러리가 포함되어 있습니다. 불행히도 @overload 데코 레이팅 된 메소드 뒤에 다른 인수를 처리하는 데코 레이팅되지 않은 메소드가 필요하기 때문에 코드를 더 읽기 쉽게 만듭니다. 여기에 있지만 더 많은 예제가 있습니다.

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)

1
답의 끝에있는 "The"는 답을 쓰지 않았다고 생각합니다. 제발 편집 을 완료 답변을.
Artjom B.

0

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를 사용하여 메소드를 오버로드 할 수 있습니다


이를 위해서는 파이썬 코어의 일부가 아닌 다중 디스패치 패키지 ( pypi.org/project/multipledispatch )를 사용해야합니다 .
Antony

0

파이썬은 @overload 데코레이터에 PEP-3124 를 추가하여 덮어 쓰기 작업 대신 형식 검사를 통한 과부하를위한 구문 설탕을 제공했습니다.

PEP-3124의 @overload를 통한 과부하 코드 예제

from overloading import overload
from collections import Iterable

def flatten(ob):
    """Flatten an object to its component iterables"""
    yield ob

@overload
def flatten(ob: Iterable):
    for o in ob:
        for ob in flatten(o):
            yield ob

@overload
def flatten(ob: basestring):
    yield ob

@ overload-decorator에 의해 다음과 같이 변환됩니다.

def flatten(ob):
    if isinstance(ob, basestring) or not isinstance(ob, Iterable):
        yield ob
    else:
        for o in ob:
            for ob in flatten(o):
                yield ob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.