Как использовать перегрузку метода в 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)

Как мне сделать эту работу?

Ответ 1

Этот метод перегружает не переопределение метода. И в Python вы делаете все это в одной функции:

class A:

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

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

У вас не может быть два метода с тем же именем в Python - и вам не нужно.

См. раздел Параметр аргумента в уроке Python. См. "Наименьшее удивление" . и Mutable Default Argument, чтобы избежать общей ошибки.

Изменить. См. PEP 443 для получения информации о новых общих функциях отправки в Python 3.4.

Ответ 2

В 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

Ответ 3

Вы также можете использовать 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

Ответ 4

Вы не можете, никогда не нуждаетесь и не очень хотите.

В Python все является объектом. Классы - это вещи, поэтому они - объекты. Итак, методы.

Существует объект под названием A, который является классом. Он имеет атрибут stackoverflow. Он может иметь только один такой атрибут.

Когда вы пишете def stackoverflow(...): ..., происходит то, что вы создаете объект, который является методом, и назначайте его атрибуту stackoverflow A. Если вы пишете два определения, второе заменит первое, то же самое, что всегда будет выполняться присваивание.

Кроме того, вы не хотите писать код, который делает более дикие вещи, для которых иногда используется перегрузка. Это не то, как работает язык.

Вместо того, чтобы пытаться определить отдельную функцию для каждого типа вещи, которую вы можете дать (что мало смысла, поскольку вы не указываете типы параметров функции в любом случае), перестаньте беспокоиться о том, что есть и начните думать о том, что они могут сделать.

Вы не только не можете написать отдельный файл для обработки кортежа и списка, но также не хотите или нуждаетесь.

Все, что вы делаете, это воспользоваться тем фактом, что они оба, например, итерабельны (т.е. вы можете написать for element in container:). (Тот факт, что они не связаны напрямую по наследству, не имеет значения.)

Ответ 5

Я пишу свой ответ в Python 3.2.1.

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

Как это работает:

  • overload принимает любое количество вызовов и сохраняет их в кортеже functions, а затем возвращает lambda.
  • Лямбда принимает любые аргументы, затем возвращает результат функции вызова, хранящийся в 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) \
    )

Ответ 6

Я думаю, что слово, которое вы ищете, это "перегрузка". В python нет перегрузки методов. Однако вы можете использовать аргументы по умолчанию, как показано ниже.

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

Когда вы передадите ему аргумент, он будет следовать логике первого условия и выполнить первый оператор печати. Когда вы передадите ему никаких аргументов, он перейдет в условие else и выполнит второй оператор печати. ​​

Ответ 7

Я пишу свой ответ в 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

Ответ 8

В Python перегрузка не является прикладной концепцией. Однако, если вы пытаетесь создать случай, когда, например, вы хотите, чтобы один инициализатор выполнялся, если передан аргумент типа foo и другой инициализатор для аргумента типа bar, тогда, поскольку обрабатывается все в Python как объект, вы можете проверить имя типа класса пройденного объекта и записать на него условную обработку.

class A:
   def __init__(self, arg)
      # Get the Argument 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

В Python вы сделаете это с аргументом по умолчанию.

class A:

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

Ответ 10

Просто наткнулся на этот https://github.com/bintoro/overloading.py для всех, кому это может быть интересно.

Из связанного репозитория readme:

Перегрузка - это модуль, который обеспечивает диспетчеризацию функций на основе типов и количества аргументов времени выполнения.

Когда вызывается перегруженная функция, диспетчер сравнивает предоставленные аргументы с доступными сигнатурами функций и вызывает реализацию, которая обеспечивает наиболее точное соответствие.

Характеристики

Проверка функций при регистрации и подробные правила разрешения гарантируют уникальный, четко определенный результат во время выполнения. Реализует кэширование разрешения функций для обеспечения высокой производительности. Поддерживает необязательные параметры (значения по умолчанию) в сигнатурах функций. Оценивает как позиционные, так и ключевые аргументы при поиске наилучшего соответствия. Поддерживает резервные функции и выполнение общего кода. Поддерживает аргумент полиморфизм. Поддерживает классы и наследование, в том числе методы класса и методы static.

Ответ 11

Хотя @agf был прав с ответом в прошлом, теперь с PEP-3124 мы получили наш синтаксис sugger. См. @overload документацию для получения подробной информации о декораторе @overload но обратите внимание, что это на самом деле просто синтаксический sugger и IMHO, это все, о чем люди спорили с тех пор. Лично я согласен с тем, что наличие нескольких функций с разными сигнатурами делает его более читабельным, чем наличие одной функции с аргументами 20+, для которых все установлено значение по умолчанию (None большую часть времени), а затем необходимость возиться с использованием бесконечных if, elif, else цепочки, чтобы выяснить, что на самом деле хочет, чтобы вызывающая сторона сделала нашу функцию с предоставленным набором аргументов. Это, это давно пора после 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>

Ответ 12

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/

Ответ 13

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)

Ответ 14

В файле 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