Основи аргументів функцій викладено на сторінці концепція функцій.
Назви параметрів, як і назви змінних, мають починатися з літери або знака підкреслення та можуть містити літери, знаки підкреслення або цифри. Назви параметрів не повинні містити пробілів або розділових знаків.
Позиційні аргументи - це значення, які передають у функцію в тому самому порядку, у якому з ними звʼязуються параметри. Позиційні аргументи можна за бажанням передати, скориставшись назвою відповідного параметра:
def concat(greeting, name):
return f"{greeting}{name}"
# Passing data to the function by position.
print(concat("Hello, ", "Lilly"))
#-> Hello, Lilly
# Passing data to the function using the parameter name.
print(concat(name="Glenn", greeting="Hello, "))
#-> Hello, Glenn
Перший виклик concat передає аргументи за позицією.
Другий виклик concat передає аргументи за назвою, що дозволяє змінити їхні позиції.
Зауважмо, що позиційні аргументи не можуть іти після аргументів, переданих за назвою (їх ще називають іменованими аргументами. Не варто плутати з параметрами зі змінною позицією або **kwargs).
Такий набір аргументів:
print(concat(greeting="Hello, ", "Gregor"))
Призводить до такої помилки:
SyntaxError: positional argument follows keyword argument
Зробити так, щоб під час виклику функції аргументи могли бути лише позиційними, можна за допомогою оператора / у списку параметрів:
# Parameters showing a position-only operator.
def concat(greeting, name, /):
return f"{greeting}{name}"
print(concat("Hello, ", "Ginnie"))
#-> Hello, Ginnie
# Call to the function using keyword arguments.
print(concat(name="Franklin", greeting="Hello, "))
Traceback (most recent call last):
print(concat(name="Franklin", greeting="Hello, "))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting, name'
Іменовані аргументи використовують назву параметра під час виклику функції. Їх за бажанням можна передавати й за позицією:
def concat(greeting, name):
return f"{greeting}{name}"
# Function call using parameter names as argument keywords.
print(concat(name="Eliza", greeting="Hello, "))
#-> Hello, Eliza
# Function call with positional data as arguments.
print(concat("Hello, ", "Tim"))
#-> Hello, Tim
Зробити так, щоб під час виклику функції аргументи могли бути лише іменованими, можна за допомогою оператора * у списку параметрів:
# Function definition requiring keyword-only arguments.
def concat(*, greeting, name):
return f"{greeting}{name}"
# Keyword arguments can be in an arbitrary order.
print(concat(name="Kimmie", greeting="Hello, "))
#-> Hello, Kimmie
# Calling the function with positional data raises an error.
print(concat("Hello, ", "Coleen"))
Traceback (most recent call last):
print(concat("Hello, ", "Coleen"))
TypeError: concat() takes 0 positional arguments but 2 were given
У списку параметрів можна вказати типові значення для одного чи кількох аргументів. Це дає змогу за потреби викликати функцію з меншою кількістю аргументів. Типові значення можна перевизначити, викликавши функцію з новим значенням аргументу, яке замінить типове:
# Function with default argument values.
def concat(greeting, name="you", punctuation="!"):
return f"{greeting}, {name}{punctuation}"
print(concat("Hello"))
#-> Hello, you!
# Overriding the default values
print(concat("Hello", name="Polly", punctuation="."))
#-> Hello, Polly.
Аргументи можуть бути позиційними або іменованими, якщо у визначенні параметрів не використано ані оператор /, ані *.
Або ж позиційні (чи іменовані) аргументи можна розмістити між лише позиційними параметрами ліворуч і лише іменованими параметрами праворуч:
# Position-only argument followed by position-or-keyword, followed by keyword-only.
def concat(greeting, /, name, *, ending):
return f"{greeting}{name}{ending}"
print(concat("Hello, ", "Mark", ending="!"))
#-> Hello, Mark!
print(concat("Hello, ", name="Rachel", ending="!"))
#-> Hello, Rachel!
print(concat(greeting="Hello, ", name="JoJo", ending="!"))
Traceback (most recent call last):
print(concat(greeting="Hello, ", name="JoJo", ending="!"))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting'
*argsУ прикладах коду часто трапляється визначення функції, схоже на таке:
def my_function(*args, **kwargs):
# code snipped
*args - це назва із двох частин, що позначає tuple з невизначеною кількістю окремих позиційних аргументів, який також називають variadic argument.
args - це назва, дана tuple аргументів, але нею може бути будь-яке інше допустиме імʼя в Python, наприклад my_args, arguments тощо.
* - це оператор, який перетворює групу окремих аргументів на tuple.
Якщо колись доводилося розпаковувати кортеж, * у *args може здатися заплутаним.
* у визначенні параметра не розпаковує кортеж, а натомість перетворює один або кілька позиційних аргументів на кортеж.
Кажемо, що оператор * перевантажений, адже в різних контекстах він поводиться по-різному.
Наприклад, * використовують для множення, для розпакування та для визначення довільної кількості позиційних параметрів.
Оскільки tuple можна перебирати, args можна передати в будь-яку іншу функцію, яка приймає обʼєкт, який можна перебрати.
Хоча *args часто ставлять поруч із **kwargs, це не обовʼязково:
def add(*args):
# args is passed to the sum function, which iterates over it.
return sum(args)
print(add(1, 2, 3))
#-> 6
Якщо *args стоїть після одного або кількох позиційних аргументів, то в *args потрапить усе, що залишиться після них:
def add(first, *args):
# first will be 1, leaving the values 2 and 3 in *args
return first + sum(args)
print(add(1, 2, 3))
#-> 6
Якщо після *args визначено один або кілька типових аргументів, вони не входять до значень *args:
def add(first, *args, last=0):
return first + sum(args) + last
print(add(1, 2, 3))
#-> 6
print(add(1, 2, 3, last=4))
#-> 10
# This uses the unpacking operator * to separate the list elements into positional arguments.
# It does not have the same behavior as the * (packing) in *args.
print(add(*[1, 2, 3]))
#-> 6
Зауважмо, що коли аргумент уже міститься всередині iterable (наприклад, tuple або list), його потрібно розпакувати, перш ніж передавати у функцію, яка приймає довільну кількість окремих аргументів.
Це роблять за допомогою *, тобто оператора розпакування.
* у цьому контексті розпаковує контейнер на окремі елементи, які потім *args перетворює на tuple.
Коли є лише позиційні аргументи, розпакування має дати таку саму кількість аргументів, скільки визначено формальних параметрів.
Без розпакування списку, переданого в add, програма видала б помилку:
def add(first, *args, last=0):
return first + sum(args) + last
print(add([1, 2, 3]))
Traceback (most recent call last):
print(add([1, 2, 3]))
return first + sum(args) + last
TypeError: can only concatenate list (not "int") to list
**kwargs**kwargs - це назва із двох частин, що позначає невизначену кількість окремих аргументів у вигляді пар ключ-значення.
kwargs - це назва групи аргументів, і нею може бути будь-яке інше імʼя, наприклад my_args, arguments тощо.
** перетворює групу іменованих аргументів на dictionary із пар {argument name: argument value}.
Оскільки словник можна перебирати, kwargs можна передати в будь-яку іншу функцію, яка приймає обʼєкт, який можна перебрати.
Хоча **kwargs часто ставлять поруч із *args, це не обовʼязково:
def add(**kwargs):
return sum(kwargs.values())
print(add(one=1, two=2, three=3))
#-> 6
Зауважмо, що метод dict.values() викликають, щоб перебрати values словника kwargs.
Коли перебираємо словник, типово перебираються keys, тож dict.values() потрібно вказати явно:
def concat(**kwargs):
# Join concatenates the tuples from `kwargs.items()`
return " ".join((str(item) for item in kwargs.items()))
print(concat(one=1, two=2, three=3))
#-> ('one', 1) ('two', 2) ('three', 3)