Передаются ли параметры в Python по значению или по ссылке
Что проверяют
Понимаете ли вы объектную модель языка и умеете ли объяснить, почему одна функция меняет данные вызывающего кода, а другая нет. Для data-ml это ещё и вопрос про гигиену: не портите ли вы входной датафрейм или массив по дороге.
Как отвечать
Ни по значению, ни по ссылке в классическом смысле. В Python передача объектной ссылки по значению: имя это ярлык на объект, в функцию попадает копия ярлыка. Отсюда два следствия. Присваивание имени внутри функции переклеивает только локальный ярлык, снаружи ничего не меняется, и именно это отличает Python от настоящей передачи по ссылке. Изменение объекта на месте видно снаружи, если объект изменяемый.
def f(lst, x):
lst.append(1) # видно снаружи
lst = [9] # только локальное имя
x += 1 # int неизменяем, у вызывающего прежнееДля работы с данными полезно сразу перевести это в практику: срез numpy это представление, a[:] = 0 меняет исходный массив, а a = a + 1 создаёт новый; у pandas часть методов возвращает новый объект, часть умеет inplace, и надёжнее явный .copy() на входе в функцию, чем догадки о том, вернулась копия или вид.
Где спотыкаются
Заучивают фразу «в Python всё передаётся по ссылке», а потом не могут объяснить, почему x += 1 для числа не виден снаружи. Формулировка про ссылку на объект плюс изменяемость снимает противоречие сразу.
Второе: изменяемое значение по умолчанию. Список или словарь в сигнатуре создаётся один раз при определении функции и копит состояние между вызовами. Правильно ставить None и создавать объект внутри.
Третье: функция подготовки признаков молча мутирует переданный датафрейм. Эксперимент перестаёт воспроизводиться, потому что второй запуск получает уже изменённые данные, а расхождение метрик списывают на случайность. Либо возвращайте новый объект, либо честно называйте функцию так, чтобы мутация была видна.