HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Давайте попробуем реализовать очень простую функцию, суммирующую числа. Для начала определим функцию sum(), принимающую на вход два числа и возвращающую их сумму:</p>
1 <p>Давайте попробуем реализовать очень простую функцию, суммирующую числа. Для начала определим функцию sum(), принимающую на вход два числа и возвращающую их сумму:</p>
2 <p>Пока всё просто и понятно. Сложности возникают при дополнительных требованиях: что, если захотим суммировать не два, а три числа? Или пять, или даже десять? Писать для обработки каждого случая отдельную функцию - очевидно плохой вариант:</p>
2 <p>Пока всё просто и понятно. Сложности возникают при дополнительных требованиях: что, если захотим суммировать не два, а три числа? Или пять, или даже десять? Писать для обработки каждого случая отдельную функцию - очевидно плохой вариант:</p>
3 <p>Надо, чтобы единая функция могла работать с разным количеством аргументов. Как это сделать?</p>
3 <p>Надо, чтобы единая функция могла работать с разным количеством аргументов. Как это сделать?</p>
4 <p>Можно заметить, что в стандартной библиотеке Python существуют функции, которые могут принимать разное количество аргументов. Например, сигнатура функции<a>max()</a>определяется так:</p>
4 <p>Можно заметить, что в стандартной библиотеке Python существуют функции, которые могут принимать разное количество аргументов. Например, сигнатура функции<a>max()</a>определяется так:</p>
5 <p>Она говорит нам о том, что в max() передается 2 обязательных аргумента (arg1 и arg2) и еще любое количество аргументов (*args):</p>
5 <p>Она говорит нам о том, что в max() передается 2 обязательных аргумента (arg1 и arg2) и еще любое количество аргументов (*args):</p>
6 <p>С точки зрения вызова - ничего необычного, просто разное число аргументов. А вот определение функции с переменным числом аргументов выглядит необычно:</p>
6 <p>С точки зрения вызова - ничего необычного, просто разное число аргументов. А вот определение функции с переменным числом аргументов выглядит необычно:</p>
7 <p>Символ астериска * перед именем позиционного параметра в определении функции обозначает оператор упаковки (строго говоря, у *-оператора нет формального имени, но в документации *args называют "arguments packing", потому мы решили придерживаться имени "оператор упаковки"). Запись *args в определении func() из примера выше означает буквально следующее: "все переданные при вызове функции аргументы поместить в кортеж args".</p>
7 <p>Символ астериска * перед именем позиционного параметра в определении функции обозначает оператор упаковки (строго говоря, у *-оператора нет формального имени, но в документации *args называют "arguments packing", потому мы решили придерживаться имени "оператор упаковки"). Запись *args в определении func() из примера выше означает буквально следующее: "все переданные при вызове функции аргументы поместить в кортеж args".</p>
8 <p>Если вовсе не передать аргументов, то кортеж args будет пустым:</p>
8 <p>Если вовсе не передать аргументов, то кортеж args будет пустым:</p>
9 <p>В функцию можно передать любое количество аргументов - все они попадут в кортеж args:</p>
9 <p>В функцию можно передать любое количество аргументов - все они попадут в кортеж args:</p>
10 <p>Аргументы могут быть любого типа - числа, строки, списки:</p>
10 <p>Аргументы могут быть любого типа - числа, строки, списки:</p>
11 <p>Теперь у нас достаточно знаний, чтобы с помощью оператора упаковки переписать нашу функцию sum() так, чтобы она умела суммировать любое количество чисел:</p>
11 <p>Теперь у нас достаточно знаний, чтобы с помощью оператора упаковки переписать нашу функцию sum() так, чтобы она умела суммировать любое количество чисел:</p>
12 <p>В таком контексте кортеж можно считать как "необязательные параметры", в которые можно либо вовсе не передавать, либо передавать столько, сколько хочешь. А что, если мы захотим, чтобы функция имела два обыкновенных, "обязательных" параметра, а остальные были необязательными? Всё просто: при определении функции сначала указываем стандартные параметры (например, a и b) и в конце добавляем *args:</p>
12 <p>В таком контексте кортеж можно считать как "необязательные параметры", в которые можно либо вовсе не передавать, либо передавать столько, сколько хочешь. А что, если мы захотим, чтобы функция имела два обыкновенных, "обязательных" параметра, а остальные были необязательными? Всё просто: при определении функции сначала указываем стандартные параметры (например, a и b) и в конце добавляем *args:</p>
13 <p>То же можно сделать и для одного параметра:</p>
13 <p>То же можно сделать и для одного параметра:</p>
14 <p>и для трёх:</p>
14 <p>и для трёх:</p>
15 <p>Эту идею можно продолжать и дальше, делая обязательными то количество параметров, которое требуется. Единственное ограничение: оператор упаковки может быть использован только для последнего параметра. То есть такой код синтаксически неверен:</p>
15 <p>Эту идею можно продолжать и дальше, делая обязательными то количество параметров, которое требуется. Единственное ограничение: оператор упаковки может быть использован только для последнего параметра. То есть такой код синтаксически неверен:</p>
16 <h2>Упаковка именованных аргументов</h2>
16 <h2>Упаковка именованных аргументов</h2>
17 <p>Для упаковки именованных аргументов существует свой оператор - **, "keyword argument packing". По аналогии с упаковкой позиционных аргументов, этот оператор упаковывает именованные аргументы, но, как вы могли догадаться, не в кортеж, а словарь.</p>
17 <p>Для упаковки именованных аргументов существует свой оператор - **, "keyword argument packing". По аналогии с упаковкой позиционных аргументов, этот оператор упаковывает именованные аргументы, но, как вы могли догадаться, не в кортеж, а словарь.</p>
18 <p>Так как **kwargs будут преобразованы в словарь, то мы можем работать с ними как с любыми словарями:</p>
18 <p>Так как **kwargs будут преобразованы в словарь, то мы можем работать с ними как с любыми словарями:</p>
19 <p>Разумеется мы можем сочетать все способы объявления аргументов. Главное, стоит помнить, что позиционные аргументы (*args тоже позиционные) идут впереди именованных.</p>
19 <p>Разумеется мы можем сочетать все способы объявления аргументов. Главное, стоит помнить, что позиционные аргументы (*args тоже позиционные) идут впереди именованных.</p>
20 <h2>Выводы</h2>
20 <h2>Выводы</h2>
21 <p>В этом уроке мы научились создавать функции с переменным числом параметров, используя оператор упаковки. Операторы * и ** упаковывают в себя переданные аргументы и позволяют работать с ними как с коллекциями: кортежами или словарями.</p>
21 <p>В этом уроке мы научились создавать функции с переменным числом параметров, используя оператор упаковки. Операторы * и ** упаковывают в себя переданные аргументы и позволяют работать с ними как с коллекциями: кортежами или словарями.</p>