В этот раз мы вызовем функцию menu(), не передав ей аргумент dessert:
>>>> menu('chardonnay', 'chicken')
>{'dessert': 'pudding', 'wine': 'chardonnay', 'entree': 'chicken'}
Если вы предоставите аргумент, он будет использован вместо аргумента по умолчанию:
>>>> menu('dunkelfelder', 'duck', 'doughnut')
>{'dessert': 'doughnut', 'wine': 'dunkelfelder', 'entree': 'duck'}
Значение аргументов по умолчанию высчитывается, когда функция определяется, а не выполняется. Распространенной ошибкой новичков (и иногда не совсем новичков) является использование изменяемого типа данных вроде списка или словаря в качестве аргумента по умолчанию.
В следующей проверке ожидается, что функция buggy() будет каждый раз запускаться с новым пустым списком result, добавлять в него аргумент arg, а затем выводить на экран список, состоящий из одного элемента. Однако в этой функции есть баг: список будет пуст только при первом вызове. Во второй раз список result будет содержать элемент, оставшийся после предыдущего вызова:
>>>> def buggy(arg, result=[]):
>…·····result.append(arg)
>…·····print(result)
>…
>>>> buggy('a')
>['a']
>>>> buggy('b')···# ожидаем увидеть ['b']
>['a', 'b']
Функция работала бы корректно, если бы код выглядел так:
>>>> def works(arg):
>…·····result = []
>…·····result.append(arg)
>…·····return result
>…
>>>> works('a')
>['a']
>>>> works('b')
>['b']
Решить проблему можно, передав в функцию что-то еще, чтобы указать на то, что вызов является первым:
>>>> def nonbuggy(arg, result=None):
>…·····if result is None:
>…·········result = []
>…·····result.append(arg)
>…·····print(result)
>…
>>>> nonbuggy('a')
>['a']
>>>> nonbuggy('b')
>['b']
Получаем позиционные аргументы с помощью *
Если вы работали с языками программирования C или C++, то можете предположить, что астериск (*) в Python как-то относится к указателям. Это не так, Python не имеет указателей.
Если символ * будет использован внутри функции с параметром, произвольное количество позиционных аргументов будет сгруппировано в кортеж. В следующем примере args является кортежем параметров, который был создан из аргументов, переданных в функцию print_args():
>>>> def print_args(*args):
>…·····print('Positional argument tuple:', args)
>…
Если вы вызовете функцию без аргументов, то получите пустой кортеж:
>>>> print_args()
>Positional argument tuple: ()
Все аргументы, которые вы передадите, будут выведены на экран как кортеж args:
>>>> print_args(3, 2, 1, 'wait!', 'uh…')
>Positional argument tuple: (3, 2, 1, 'wait!', 'uh…')
Это полезно при написании функций вроде print(), которые принимают произвольное количество аргументов. Если в вашей функции имеются также обязательные позиционные аргументы, *args отправится в конец списка и получит все остальные аргументы: