Подтвердить что ты не робот

Python - как работают передаточные значения?

У меня есть вопрос о вызовах функций в Python. Скажем, я хочу написать функцию superLongFunc (expr). Функция очень длинная и очень сложная для отладки. Я хочу разбить функцию на более мелкие вспомогательные функции для лучшей читаемости, на что-то вроде smallFunc1 (expr), smallFunc2 (expr) и т.д.

Мой вопрос в том, влияет ли это на производительность кода вообще? Как точно работают функции вызова в Python? Передает ли Python переменные функции по ссылке? Или он делает копию переменной перед подачей ее на функцию?

Я знаю, что это довольно шумный вопрос, но это немного исказило меня. Спасибо заранее!

4b9b3361

Ответ 1

Python использует систему, которая иногда называется call-by-object. При передаче аргументов функции не копируется. Имена аргументов функции локально связаны внутри тела функции с теми же объектами, что и в вызове функции.

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

>>> def func(x):
...     x[0] = 2 # Mutating the object affects the object outside the function
>>> myList = [1]
>>> func(myList)
>>> myList # myList has changed
[2]
>>> def func(x):
...     x = 2 # rebinding name has no effect outside the function
>>> myList = [1]
>>> func(myList)
>>> myList # myList is unaffected
[1]

Мое простое мышление об этом заключается в том, что присваивание общему имени --- то есть инструкции формы name = value --- полностью отличаются от всего остального в Python. Единственный способ работать с именами, а не по значениям, - это сделать name = value. (Есть исключения из-за этого, например, с помощью globals() и т.д., Но это опасная территория). В частности, name = value отличается от obj.prop = value, obj[0] = value, obj += value и других подобных вещи, которые похожи на присвоение, но фактически работают с объектами, а не с именами.

Тем не менее, вызовы функций в Python имеют определенное количество накладных расходов только сами по себе (для настройки кадра выполнения и т.д.). Если функция вызывается много раз, эти издержки могут вызвать заметное влияние производительности. Таким образом, разделение одной функции на многие может по-прежнему оказывать влияние на производительность, поскольку каждый дополнительный вызов функции добавит некоторые накладные расходы.