Передача аргументов функции Python внутри функции

В случае, показанном ниже, у меня есть функция под названием func1(), которая находится в func3(), где func3() вычисляет значение ОДУ с использованием метода Эйлера.

def func1(x, y):
    return y * np.log(y) / x

def func3(x, y, step_size, func):
    dydx = func(x, y)
    new_x = x + step_size
    new_y = y _ step_size * dydx
    return new_x, new_y

step_size - 0.1
lower = 2.0
upper = 3.0
e = 2.7182828284

x_val = [2.0]
y_val = [e]
for i in range(10):
    x, y = func3(x_val[i], y_val[i], step_size, func1)
    x_val.append(x)
    y_val.append(y)

Код передает func1 в func3 в качестве декоратора и записывает вывод в список по мере итерации в диапазоне от 0 до 10. Однако код внутри func3() жестко закодирован для точного ввода func1(), то есть x и y. Я хотел бы написать func3(), чтобы он был достаточно общим, чтобы вы могли передать ему любую функцию, если его первые два входа — x и y, но он должен быть способен принимать больше входных данных. Итак, предположим, что весь код, показанный выше, был идентичен, но вместо передачи func1() я передал func2() в func3() со структурой, показанной ниже.

def func2(x, y, z):
    return z * y * np.log(y) / (x*z)

Как я мог написать func3(), чтобы он был достаточно универсальным, чтобы он мог принимать любую из двух функций и понимать, что у них больше аргументов для передачи в func1(), которые также должны быть переданы в func3()?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
85
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Используйте *args и **kwargs для сбора аргументов (в дополнение к x и y, предназначенным для вашего обратного вызова):

def func3(x, y, step_size, func, *args, **kwargs):
    dydx = func(x, y, *args, **kwargs)
    ...

Однако подумайте, действительно ли func3 необходимо вызывать func себя; вместо этого сделайте это абонент.

def func3(x, y, step_size, dydx):
    new_x = x + step_size
    new_y = y - step_size * dydx
    return new_x, new_y

for old_x, old_y in zip(x_val, y_val):
    x, y = func3(old_x, old_y, step_size, func1(x, y))
    ...
Ответ принят как подходящий

Вы можете использовать синтаксис аргументов переменной длины Python для ожидания любых дополнительных аргументов и передачи их дальше. Если их нет, то все равно работает: переменная со звездочкой получит в качестве значения пустой список и исчезнет при расширении осенью до func.

def func1(x, y):
    return x+y

def func2(x, y, z):
    return (x+y)*z

def caller(func, x, y, other, other2, *args):
    return func(x, y, *args)

Спасибо, я использовал тот же подход, но с **kwargs, чтобы убедиться, что передаются правильные переменные.

Jon 23.04.2019 22:04

Звучит как хорошая идея: если вы перепутаете аргументы, вы сразу узнаете.

alexis 24.04.2019 01:22

Было бы лучше использовать *args и **kargs (**kwargs в определениях функций в python используется для передачи списка аргументов переменной длины с ключевыми словами. Мы используем имя kwargs с двойной звездочкой. Причина в том, что двойная star позволяет нам передавать аргументы ключевых слов и любое их количество).

Например:

def myFun (arg1, arg2, arg3):

print("arg1:", arg1) 

print("arg2:", arg2) 

print("arg3:", arg3) 

args = ("Привет", "привет", "пока")

myFun(*аргументы)

kwargs = {"arg1" : "компьютерщик", "arg2" : "ботаник", "arg3" : "нуб" }

myFun(**kwargs)

Выход: Привет Привет до свидания Компьютерщик Зануда Новичек

Я не думаю, что вам действительно нужно принимать другие аргументы, кроме x и y, или менять func3.

Предположим, вы хотите передать z внутренней функции. И вам также нужно передать его в func3. Поскольку z не изменится во время вызова func3, вы можете просто сделать что-то вроде func3(x, y, lambda x, y : your_func (x, y , z), step) и использовать функции с любым количеством аргументов через лямбду, которая принимает x и y.

В вашем случае вызов будет выглядеть так:

x, y = func3(x_val[i], y_val[i], step_size, lambda x, y: func2(x, y, 111))

Другие вопросы по теме