programing tip

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

itbloger 2020. 6. 16. 20:37
반응형

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


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

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)

이 작업을 어떻게합니까?


그것은의 메소드 오버로딩은 방법이 아니다 오버라이드 (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참조하십시오 .


파이썬에서는 그런 식으로 일을하지 않습니다. 사람들이 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

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

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

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

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

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

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

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

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

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


파이썬 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) \
    )

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

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

When you pass it an argument it will follow the logic of the first condition and execute the first print statement. When you pass it no arguments, it will go into the else condition and execute the second print statement.


I write my answer in Python 2.7:

In Python, method overloading is not possible; if you really want access the same function with different features, I suggest you to go for method overriding.

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

In Python, overloading is not an applied concept. However, if you are trying to create a case where, for instance, you want one initializer to be performed if passed an argument of type foo and another initializer for an argument of type bar then, since everything in Python is handled as object, you can check the name of the passed object's class type and write conditional handling based on that.

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

This concept can be applied to multiple different scenarios through different methods as needed.


In Python, you'd do this with a default argument.

class A:

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

While @agf was right with the answer in the past now with PEP-3124 we got our syntax sugger. See typing documentation for details on the @overload decorator but note that this is really just syntax sugger and IMHO this is all people have been arguing about ever since. Personally I agree that having multiple functions with different signatures makes it more readable then having a single function with 20+ arguments all set to a default value (None most of the time) and then having to fiddle around using endless if, elif, elsechains to find out what the caller actually wants our function to do with the provided set of arguments. This, this is long overdue following the Python Zen

Beautiful is better than ugly.

and arguably also

Simple is better than complex.

Straight from the official Python documentation linked above:

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

Just came across this https://github.com/bintoro/overloading.py for anybody who may be interested.

From the linked repository's readme:

overloading is a module that provides function dispatching based on the types and number of runtime arguments.

When an overloaded function is invoked, the dispatcher compares the supplied arguments to available function signatures and calls the implementation that provides the most accurate match.

Features

Function validation upon registration and detailed resolution rules guarantee a unique, well-defined outcome at runtime. Implements function resolution caching for great performance. Supports optional parameters (default values) in function signatures. Evaluates both positional and keyword arguments when resolving the best match. Supports fallback functions and execution of shared code. Supports argument polymorphism. Supports classes and inheritance, including classmethods and staticmethods.


Python does not support method overloading like Java or C++. We may overload the methods but can only use the latest defined method.

# 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)

We need to provide optional arguments or *args in order to provide different number of args on calling.

Courtesy from https://www.geeksforgeeks.org/python-method-overloading/


Python 3.x includes standard typing library which allows for method overloading with the use of @overload decorator. Unfortunately, this is to make the code more readable, as the @overload decorated methods will need to be followed by a non-decorated method that handles different arguments. More can be found here here but for your example:

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)

In MathMethod.py file

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

In Main.py file

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

We can overload method by using multipledispatch

참고URL : https://stackoverflow.com/questions/10202938/how-do-i-use-method-overloading-in-python

반응형