Передача аргументов в функцию
Как в python передаются аргументы в функцию?
подробнее
Есть 2 типа передачи аргументов в функцию: по ссылке и по значению. В python аргументы передаются по ссылке.
# Пример:
a = [1, 2, 3]
def foo(arg):
print(arg is a)
foo(a) # True
Что такое *args и **kwargs?
подробнее
*args— позволяет функции принимать произвольное количество позиционных аргументов (упаковывает их в кортеж)**kwargs— позволяет функции принимать произвольное количество именованных аргументов (упаковывает их в словарь)
# пример
def my_function(arg1, arg2, *args, kwarg1=None, **kwargs):
print(f"Обязательные аргументы: {arg1}, {arg2}") # 1, 2
print(f"Дополнительные позиционные: {args}") # (3, 4, 5)
print(f"Обязательный именованный: {kwarg1}") # required
print(f"Дополнительные именованные: {kwargs}") # {'extra1': 'a', 'extra2': 'b'}
my_function(1, 2, 3, 4, 5, kwarg1="required", extra1="a", extra2="b")
# пример 2
def foo(*args, **kwargs):
print(locals())
foo(1, 2, 3, a=1, b=2, c=3) # {'args': (1, 2, 3), 'kwargs': {'a': 1, 'b': 2, 'c': 3}}
Значение изменяемого типа в качестве аргумента по умолчанию.
подробнее
Когда в качестве значения по умолчанию используется изменяемый объект (список, словарь, множество), он создается один раз во время определения функции, а не при каждом вызове.
Пример проблемы
# НЕПРАВИЛЬНО
def add_item(item, target_list=[]):
target_list.append(item)
return target_list
# Проблема:
list1 = add_item(1)
print(list1) # [1]
list2 = add_item(2)
print(list2) # [1, 2] - ОЖИДАЛИ [2]!
print(list1) # [1, 2] - Исходный список тоже изменился!
Почему это происходит
def demonstrate_issue(default_list=[]):
print(f"ID списка: {id(default_list)}")
default_list.append("item")
return default_list
# При каждом вызове используется один и тот же объект
result1 = demonstrate_issue() # ID списка: 140234567890
result2 = demonstrate_issue() # ID списка: 140234567890 (тот же!)
Пример исправления
# Использование None как значения по умолчанию
def add_item(item, target_list=None):
if target_list is None:
target_list = [] # Создаем новый список при каждом вызове
target_list.append(item)
return target_list