Шаг 116.
Основы языка Python.
Пользовательские функции. Необязательные параметры и сопоставление по ключам

    На этом шаге мы рассмотрим особенности передачи параметров.

    Чтобы сделать некоторые параметры необязательными, следует в определении функции присвоить этому параметру начальное значение. Переделаем функцию суммирования двух чисел и сделаем второй параметр необязательным.

def summa(x, y=2): # y - необязательный параметр
    return x + y

а = summa(5) # Переменной a будет присвоено значение 7
b = summa(10, 50) # Переменной b будет присвоено значение 60

    Таким образом, если второй параметр не задан, то его значение будет равно 2. Обратите внимание на то, что необязательные параметры должны следовать после обязательных параметров, иначе будет выведено сообщение об ошибке.

    До сих пор мы использовали позиционную передачу параметров в функцию:

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

print(summa(10, 20)) # Выведет: 30

    Переменной х при сопоставлении будет присвоено значение 10, а переменной y - значение 20. Но язык Python позволяет также передать значения в функцию, используя сопоставление по ключам. Для этого при вызове функции параметрам присваиваются значения, причем последовательность указания параметров в этом случае может быть произвольной:

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

print(summa(y=20, x=10))  # Сопоставление по ключам

    Сопоставление по ключам очень удобно использовать, если функция имеет несколько необязательных параметров. В этом случае не нужно перечислять все значения, а достаточно присвоить значение нужному параметру. Пример:

def summa(a=2, b=3, c=4): # Все параметры являются необязательными
    return a + b + c

print(summa(2, 3, 20)) # Позиционное присваивание
print(summa(c=20)) # Сопоставление по ключам

    Если значения параметров, которые планируется передать в функцию, содержатся в кортеже или списке, то перед объектом следует указать символ *. Пример передачи значений из кортежа и списка приведен ниже:

def summa(a, b, с):
    return a + b + с

t1, arr = (1, 2, 3), [1, 2, 3]
print (summa(*t1)) # Распаковываем кортеж
print(summa(*arr)) # Распаковываем список
t2 = (2, 3)
print(summa(1, *t2)) # Можно комбинировать значения

    Если значения параметров содержатся в словаре, то распаковать словарь можно, указав перед ним две звездочки (**):

def summa(a, b, с):
    return a + b + с

d1 = {"a": 1, "b": 2, "с": 3}
print(summa(**d1)) # Распаковываем словарь
t, d2 = (1, 2), {"с": 3}
print(summa(*t, **d2)) # Можно комбинировать значения

    Объекты в функцию передаются по ссылке. Если объект относится к неизменяемому типу, то изменение значения внутри функции не затронет значение переменной вне функции:

def func(a, b):
    a, b = 20, "str"

x, s = 80, "test"
func(x, s) # Значения переменных x и s не изменяются
print(x, s) # Выведет: 80 test

    В этом примере значения в переменных х и s не изменились. Однако если объект относится к изменяемому типу, то ситуация будет другой:

def func (a, b):
    a[0], b["a"] = "str", 800
    
x = [1, 2, 3] # Список
y = {"a": 1, "b": 2} #  Словарь
func(x, y) # Значения будут изменены!!!
print (x, y) # Выведет: ['str', 2, 3] {'а': 800, 'b': 2}

    Как видно из примера, значения в переменных х и y изменились, поскольку список и словарь относятся к изменяемым типам. Чтобы избежать изменения значений, внутри функции следует создать копию объекта:

def func (a, b):
    a = a[:] # Создаем поверхностную копию списка
    b = b.copy() # Создаем поверхностную копию словаря
    a[0], b["a"] = "str", 800

x = [1, 2, 3] # Список
y = {"a": 1, "b": 2} # Словарь
func(x, y) # Значения останутся прежними
print (x, y) # Выведет: [1, 2, 3] {'а': 1, 'b': 2}

    Можно также сразу передавать копию объекта в вызове функции:

  func(x[:], y.copy())

    Если указать объект, имеющий изменяемый тип, в качестве значения по умолчанию, то этот объект будет сохраняться между вызовами функции. Пример:

def func(a=[]):
    a.append(2)
    return a

print(func()) # Выведет: [2]
print(func()) # Выведет: [2, 2]
print(func()) # Выведет: [2, 2, 2]

    Как видно из примера, значения накапливаются внутри списка. Обойти эту проблему можно, например, следующим образом:

def func(a=None): # Создаем новый список, если значение равно None
    if a is None:
        a = []
    a.append(2)
    return a

print(func())    # Выведет: [2]
print(func([1])) # Выведет: [1, 2]
print(func())    # Выведет: [2]

    На следующем шаге мы рассмотрим переменное число параметров в функции.




Предыдущий шаг Содержание Следующий шаг