Какие типы данных могут быть переданы в функцию
Что проверяют
Понимаете ли вы, что в Python всё является объектом и как именно объект попадает внутрь функции. Вопрос-разминка почти всегда переходит в «по значению или по ссылке» и в ловушку с изменяемым значением по умолчанию.
Как отвечать
Короткий ответ: любой объект. Кроме чисел, строк и коллекций это None, функции и лямбды (функции первого класса), классы, модули, генераторы, экземпляры ваших классов. На этом держатся колбэки, декораторы и sorted(items, key=len).
Главное в ответе это механизм передачи. Python передаёт не значение и не ссылку в смысле C++, а ссылку на объект, это называют call by sharing. Параметр становится новым именем того же объекта:
- если объект изменяемый (
list,dict,set), изменения внутри функции видны снаружи:lst.append(1)меняет исходный список; - присваивание параметру (
lst = [1]) только перепривязывает локальное имя, снаружи ничего не меняется; - неизменяемые (
int,str,tuple) изменить нельзя в принципе, поэтому кажется, что они «передаются по значению».
Дальше про виды параметров:
- позиционные и именованные, значения по умолчанию;
- *`args
иkwargs`: произвольное число аргументов, при вызове распаковкаf(*lst, **d); - только позиционные перед
/(с Python 3.8) и только именованные после*; - аннотации типов:
def f(x: list[int]) -> None, с 3.12 обобщенияdef f[T](x: T) -> T. Интерпретатор их не проверяет, это делают mypy и pyright.
Где спотыкаются
Пишут def add(item, bucket=[]). Значение по умолчанию вычисляется один раз при определении функции, и список копится между вызовами. Правильно bucket=None и создание списка внутри.
Отвечают «числа по значению, списки по ссылке». Механизм один, разница только в изменяемости объекта.
Считают, что аннотация x: int запретит передать строку. В рантайме это просто метаданные, ошибка вылезет позже или не вылезет вовсе.