Перевантажені функції в python?


91

Чи можна мати перевантажені функції в Python? У C # я б зробив щось подібне

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

а потім, коли я викликаю функцію, вона буде диференціювати ці два залежно від кількості аргументів. Чи можна зробити щось подібне в Python?


Здається, це можлива копія публікації. Також, будь ласка, не позначайте як C #, оскільки питання не має відношення до C #. function-overloading-in-python-missing
Jethro


Відповіді:


103

РЕДАКТУВАТИ Нові загальні функції єдиного відправлення в Python 3.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,

9
Ну, є різниця між перевантаженням / поліморфізмом та умовностями. Ви маєте на увазі, що нам не потрібен поліморфізм, оскільки ми маємо умови?
Валь

1
@Val Я кажу, в основному, що в мові, що динамічно набирається, вам не потрібно перевантажувати як функцію мови, оскільки ви можете тривіально емулювати її в коді, і таким чином можна отримати поліморфізм таким чином.
agf

1
@Val Я кажу, що між необов’язковими аргументами та динамічними типами, як у вас у Python, вам не потрібно перевантажувати метод стилю Java для досягнення поліморфізму.
agf

3
@navidoo Я б стверджував, що це не є гарною ідеєю - функція не повинна повертати абсолютно різні типи речей. Однак ви завжди можете визначити локальну функцію генератора всередині основної функції, викликати її та повернути отриманий генератор - ззовні це буде те саме, що якби основною функцією був генератор. Приклад тут.
agf

50

у звичайному python ти не можеш робити те, що хочеш. є два близьких наближення:

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, але це перевантаження методів за типом. це дуже схожий підхід ...

ОНОВЛЕННЯ: і щось подібне (з використанням типів аргументів) додається до python 3 - http://www.python.org/dev/peps/pep-0443/


rangeВбудована використовує перевантаження, так що це дійсно хак? github.com/python/typeshed/blob/master/stdlib/2and3/…
CptJero

9

Так, це можливо. Я написав код нижче в Python 3.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

0

методи перевантаження складні в python. Однак може використовуватися передача dict, list або примітивних змінних.

Я спробував щось для своїх випадків використання, це може допомогти тут зрозуміти людей, які перевантажують методи.

Візьмемо приклад використання в одному з потоків stackoverflow:

метод перевантаження класу з викликом методів з іншого класу.

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']}

Отже, досягається обробка списку, словника або примітивних змінних через перевантаження методу.

спробуйте це для своїх кодів

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.