Основы соответствия аргументов при вызове функций
Позиционные: сопоставляются слева направо
Ключевые: сопоставляются по именам аргументов Вызывающий функцию может сам задать при обращении к функции какой аргумент получит значение в виде имя=значение.
По умолчанию в описании функции можно задать значения для тех параметров, которые не указаны при вызове
Коллекция Varargs: коллекция неопределенного числа позиционных или ключевых аргументов
Функции могут использовать специальные аргументы перед которыми ставят одну или две звездочки * для того, чтобы передать неопределенное число аргументов. Такая возможность часто обозначается как varargs, по аналогии с языком C; в Python, эти аргументы собираются в нормальный объект.
Неупакованные Varargs: передается неопределенно много позиционных и ключевых аргументов
При вызове функции можно использовать *синтаксис для того, что бы распаковать коллекцию аргументов в отдельные аргументы. Это обратная операция к *, указанной в описании функции - в описании функции это означает коллекцию неопределенно большого количества аргументов, а во время вызова функции это означает разбор коллекции и передачу функции членов коллекции как отдельные значения.
Только ключевые Аргументы: такие аргументы передаются по имени
В Python 3.X (но не в 2.X), в функциях могут быть заданы аргументы, которые передаются не по позиции, а по имени. Такие аргументы обычно используются для определения конфигурации дополнительно к реальным аргументам.
Формы соответствия аргументов
Синтаксис Описание
func(value) Обычный аргумент вызывающей функции: позиционное соответствие
func(name=value) Ключевой аргумент вызывающей функции: соответствие по имени
func(*iterable) Вызывающая функция передает все объекты как итерационный объект с
количеством параметров равным количеству аргументов в описании
функции
пример:
>>> def f1(a, b, c):
... print(a,b,c)
>>> f1(*(1,2,3))
1,2,3
func(**dict) Вызывающая функция передает все пары ключ/значение из словаря как
индивидуальные аргументы
>>> def f2(a, c, d):
... print(a,c,d)
>>> s = {'d':'3','a':1,'c':2}
>>> f2(**s)
1 2 3
def func(name) Нормальные аргументы функций: соответствие выполняется по позиции
или по имени
def func(name=value) Таким образом задается значение по умолчанию, если значение не
указано при вызове
def func(*name) Функция сопоставляет и собирает все оставшиеся аргументы в кортэж
def func(**name) Функция сопоставляет и собирает все оставшиеся ключевые аргументы
в словарь
def func(*other, name) Аргументы функции, которые должны быть переданы по ключу только в
момент вызова (3.X)
def func(*, name=value)Аргументы функции, которые должны быть переданы по ключу только в
момент вызова (3.X)
Эти способы вызова функций применяются следующим образом:
• При вызове функции, значения сопоставляются аргументам по их позиции, но использование формы имя=значение говорит Python использовать имя аргументов; это так называемые ключевые аргументы. Использование *iterable или **dict при вызове функции позволяет нам упаковывать произвольное количество позиционных или ключевых объектов в последовательности и словари, соответственно. При передаче в функцию они распаковываются и используются как отдельные параметры.
• При описании функции, a simple nameis matched by position or name depending on how the caller passes it, but the name=value form specifies a default value. The *nameform collects any extra unmatched positional arguments in a tuple, and the **nameform collects extra keyword arguments in a dictionary.
In Python 3.X, any normal or defaulted argument names following a *nameor a bare *are keyword-only arguments and must be passed by keyword in calls. Of these, keyword arguments and defaults are probably the most commonly used in Python code. We’ve informally used both of these earlier in this book:
• We’ve already used keywords to specify options to the 3.X print function, but they are more general - keywords allow us to label any argument with its name, to make calls more infomational.
• We met defaults earlier, too, as a way to pass in values from the enclosing function’s scope, but they are also more general—they allow us to make any argument optional, providing its default value in a function definition.
As we’ll see, the combination of defaults in a function header and keywords in a call further allows us to pick and choose which defaults to override.
In short, special argument-matching modes let you be fairly liberal about how many arguments must be passed to a function. If a function specifies defaults, they are used if you pass too few arguments. If a function uses the *variable argument list forms, you can seemingly pass too many arguments; the *names collect the extra arguments in data structures for processing in the function.
The Gritty Details
If you choose to use and combine the special argument-matching modes, Python will ask you to follow these ordering rules among the modes’ optional components:
• При вызове функции, аргументы должны появляться в вызове в следующем порядке: сначала любые позиционные аргументы (их значения); за ними идут комбинации любых ключевых аргументов (типа имя=значение) и затем *итерационные объекты; затем **объекты типа словари.
• В заголовке описания функции, аргументы должны появляться в таком порядке: всякие обычные аргументы (имена); followed by any default arguments (name=value); followed by the *name(or *in 3.X) form; followed by any nameor name=valuekeyword-only arguments (in 3.X); followed by the **nameform.
Как при вызове функций, так и при ее описании, форма **args должна появляться последней, если она присутствует. Если вы смешаете аргументы в произвольном порядке, то получите сообщение о синтаксической ошибке. Python выполняет следующие шаги для поиска соответствия между аргументами перед вызовом функции:
1. Назначение неключевых аргументов по расположению.
2. Назначение ключевых аргументов по соответствию имен.
3. Назначение экстра неключевых аргументов к кортежу вида *name.
4. Назначение экстра ключевых аргументов к словарю вида **name.
5. Назначение значений, определенных как по умолчанию в описании функции и оставшихся не определенными.
After this, Python checks to make sure each argument is passed just one value; if not, an error is raised. When all matching is complete, Python assigns argument names to the objects passed to them.
The actual matching algorithm Python uses is a bit more complex (it must also account for keyword-only arguments in 3.X, for instance), so we’ll defer to Python’s standard language manual for a more exact description. It’s not required reading, but tracing Python’s matching algorithm may help you to understand some convoluted cases, es-pecially when modes are mixed.
Python 3.X Keyword-Only Arguments
Python 3.X generalizes the ordering rules in function headers to allow us to specify keyword-only arguments-arguments that must be passed by keyword only and will never be filled in by a positional argument. This is useful if we want a function to both process any number of arguments and accept possibly optional configuration options.
Syntactically, keyword-only arguments are coded as named arguments that may appear after *argsin the arguments list. All such arguments must be passed using keyword syntax in the call. For example, in the following, amay be passed by name or position, bcollects any extra positional arguments, and cmust be passed by keyword only. In 3.X:
>>> def kwonly(a, *b, c):
... print(a, b, c)
>>> kwonly(1, 2, c=3)
1 (2,) 3
>>> kwonly(a=1, c=3)
1 () 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() missing 1 required keyword-only argument: 'c'
We can also use a *character by itself in the arguments list to indicate that a function does not accept a variable-length argument list but still expects all arguments following the *to be passed as keywords. In the next function, amay be passed by position or name again, but band cmust be keywords, and no extra positionals are allowed:
>>> def kwonly(a, *, b, c):
... print(a, b, c)
>>> kwonly(1, c=3, b=2)
1 2 3
>>> kwonly(c=3, b=2, a=1)
1 2 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() takes 1 positional argument but 3 were given
>>> kwonly(1)
TypeError: kwonly() missing 2 required keyword-only arguments: 'b' and 'c'
You can still use defaults for keyword-only arguments, even though they appear after the *in the function header. In the following code, amay be passed by name or position, and band care optional but must be passed by keyword if used:
>>> def kwonly(a, *, b='spam', c='ham'):
...print(a, b, c)
>>> kwonly(1)
1 spam ham
>>> kwonly(1, c=3)
1 spam 3
>>> kwonly(a=1)
1 spam ham
>>> kwonly(c=3, b=2, a=1)
1 2 3
>>> kwonly(1, 2)
TypeError: kwonly() takes 1 positional argument but 2 were given
In fact, keyword-only arguments with defaults are optional, but those without defaults effectively become required keywordsfor the function:
>>> def kwonly(a, *, b, c='spam'):
... print(a, b, c)
>>> kwonly(1, b='eggs')
1 eggs spam
>>> kwonly(1, c='eggs')
TypeError: kwonly() missing 1 required keyword-only argument: 'b'
>>> kwonly(1, 2)
TypeError: kwonly() takes 1 positional argument but 2 were given
>>> def kwonly(a, *, b=1, c, d=2):
print(a, b, c, d)
>>> kwonly(3, c=4)
3 1 4 2
>>> kwonly(3, c=4, b=5)
3 5 4 2
>>> kwonly(3)
TypeError: kwonly() missing 1 required keyword-only argument: 'c'
>>> kwonly(1, 2, 3)
TypeError: kwonly() takes 1 positional argument but 3 were given Ordering rules