Входные параметры в Python: базовые и продвинутые способы

Раздел: Основы Python -> Функции

Входные параметры функций в Python

Основной способ передачи данных в функцию – использование позиционных и именованных аргументов с возможностью указания значений по умолчанию. Это покрывает большинство практических случаев и делает код читаемым.

def greet(name, greeting="Hello", punctuation="!"):
    print(f"{greeting}, {name}{punctuation}")

greet("Анна")                          # Hello, Анна!
greet("Пётр", "Привет")               # Привет, Пётр!
greet("Мария", greeting="Здравствуйте") # Здравствуйте, Мария!

аргументы print python (аргументы функции print в python)

В примере name – обязательный позиционный аргумент, greeting и punctuation имеют значения по умолчанию. При вызове можно передать только обязательные аргументы, либо указать любые комбинации именованных.

Типичная ошибка: использование изменяемого объекта (например, списка) в качестве значения по умолчанию. Этот объект создаётся однократно и будет общим для всех вызовов, что может привести к неожиданным результатам.

def add_item(item, lst=[]):
    lst.append(item)
    return lst

print(add_item(1))  # [1]
print(add_item(2))  # [1, 2]  – неожиданно!

Python 3 аргументы (аргументы в python 3)

Исправление: использовать None и создавать список внутри функции.

def add_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

аргумент параметр python (аргументы и параметры в python)

Как передать произвольное количество позиционных аргументов?

Используется синтаксис *args. Звёздочка перед именем параметра упаковывает все переданные позиционные аргументы в кортеж.

def sum_all(*numbers):
    return sum(numbers)

print(sum_all(1, 2, 3))  # 6
print(sum_all(10, 20))   # 30

аргумент класса python (аргументы класса python)

Имя args – общепринятое, может быть любым. Используется, когда количество аргументов заранее неизвестно.

Проблема: если после *args определить ещё один позиционный параметр, его можно передать только по имени (ключевому слову).

def func(*args, extra):
    print(args, extra)

func(1, 2, extra=3)  # (1, 2) 3

Python аргументы строки (аргументы строки в python (командная строка))

Как передать произвольное количество именованных аргументов?

Используется **kwargs (keyword arguments). Две звёздочки упаковывают именованные аргументы в словарь.

def print_person(**info):
    for key, value in info.items():
        print(f"{key}: {value}")

print_person(name="Иван", age=30, city="Москва")

аргумент метода python (аргументы метода python)

name: Иван
age: 30
city: Москва

Python args (аргументы в python)

Имя kwargs тоже условное. Параметр **kwargs помещается в определении функции последним.

Ошибка: попытка передать позиционные аргументы после **kwargs или объявить ещё один именованный параметр после него приведёт к синтаксической ошибке.

Как задать значения по умолчанию и избежать побочных эффектов?

Значения по умолчанию вычисляются один раз в момент определения функции. Для изменяемых объектов (списки, словари) это ведёт к проблеме, описанной выше. Рекомендуется использовать None и проверять внутри тела функции.

def create_user(name, roles=None):
    if roles is None:
        roles = []
    roles.append("user")
    return {name: roles}

print(create_user("Анна"))  # {'Анна': ['user']}
print(create_user("Борис")) # {'Борис': ['user']}

именованные аргументы функции python (именованные аргументы функции python)

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

Как явно указать ожидаемый тип аргумента?

Аннотации типов (type hints) не проверяются интерпретатором, но помогают разработчикам и инструментам статического анализа (mypy).

def repeat(text: str, times: int) -> str:
    return text * times

print(repeat("Ha", 3))  # HaHaHa

именованные аргументы python (именованные аргументы python)

Аннотации указываются после двоеточия, возвращаемый тип – после ->. Сторонние библиотеки могут выполнять проверку во время выполнения.

Проблема: путаница между аннотациями и приведением типов. Аннотации не преобразуют аргументы; если передать не тот тип, ошибка не возникнет (до выполнения кода).

Как передать аргументы из списка или словаря?

Операторы распаковки * и ** применяются не только в определении функции, но и при её вызове.

def point(x, y, z):
    return (x, y, z)

coords = [10, 20, 30]
dict_coords = {"x": 1, "y": 2, "z": 3}

print(point(*coords))        # (10, 20, 30)
print(point(**dict_coords))  # (1, 2, 3)

Распаковка удобна, когда данные уже находятся в структуре, соответствующей сигнатуре функции.

Ошибка: несовпадение количества элементов в коллекции с числом параметров (при распаковке списка) или несовпадение ключей словаря с именами параметров.

- Python передать аргументы (передача аргументов в python)
- Python принять аргументы (приём аргументов в python)
- Python список аргументов (список аргументов в python)

Расширенные примеры

Комбинирование *args и **kwargs

Функция может одновременно принимать произвольное количество позиционных и именованных аргументов. Порядок параметров: сперва обычные, затем *args, потом именованные со значением по умолчанию и **kwargs.

Пример
def flexible(a, b, *args, opt="default", **kwargs):
    print(f"a={a}, b={b}, args={args}, opt={opt}, kwargs={kwargs}")

flexible(1, 2, 3, 4, opt="custom", name="test", version=1.0)
a=1, b=2, args=(3, 4), opt=custom, kwargs={'name': 'test', 'version': 1.0}

Передача произвольных аргументов в декоратор

Декоратор может принимать аргументы через вложенные функции с *args и **kwargs.

Пример
def repeat_decorator(times=1):
    def decorator(func):
        def wrapper(*args, **kwargs):
            result = None
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat_decorator(times=3)
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Мир")
Hello, Мир!
Hello, Мир!
Hello, Мир!

Использование * для разделения позиционных и именованных аргументов

Если в определении функции присутствует одиночная звёздочка, все аргументы после неё могут быть переданы только по имени (ключевому слову).

Пример
def exact(a, b, *, c, d):
    return a + b + c + d

print(exact(1, 2, c=3, d=4))  # 10
# exact(1, 2, 3, 4)  # TypeError: exact() takes 2 positional arguments but 4 were given

Аннотации типов с использованием Union и Optional

Для указания нескольких возможных типов или необязательного параметра применяются конструкции из модуля typing.

Пример
from typing import Union, Optional

def example(value: Union[int, str], multiplier: Optional[int] = None) -> str:
    if multiplier:
        return str(value * multiplier)
    return str(value)

print(example(5, 3))       # 15
print(example("Hello", 2)) # HelloHello
print(example(42))         # 42

Частичное применение аргументов с functools.partial

С помощью partial можно зафиксировать некоторые аргументы функции, создав новую функцию с меньшим числом параметров.

Пример
from functools import partial

def power(base, exponent):
    return base ** exponent

square = partial(power, exponent=2)
cube = partial(power, exponent=3)

print(square(5))  # 25
print(cube(2))    # 8

Проверка аргументов во время выполнения с помощью assert

Для жёсткого контроля можно использовать assert или сторонние библиотеки вроде pydantic.

Пример
def positive_sum(a: int, b: int) -> int:
    assert a > 0 and b > 0, "Аргументы должны быть положительными"
    return a + b

print(positive_sum(3, 4))  # 7
# print(positive_sum(-1, 5))  # AssertionError

Именованные аргументы с ключами, содержащими дефис или пробелы

Имена параметров в Python – корректные идентификаторы, поэтому ключи с дефисами передать напрямую нельзя. Решение – использовать распаковку словаря.

Пример
def process(data):
    print(data)

params = {"content-type": "application/json", "x-api-key": "123"}
process(params)

Принудительное указание именованных аргументов с *

В функциях с множеством параметров полезно заставить вызывающего указывать имена последних аргументов для улучшения читаемости.

Пример
def create_user(name, age, *, email, phone):
    pass

create_user("Иван", 30, email="ivan@example.com", phone="+7-999-111-22-33")
# create_user("Иван", 30, "ivan@example.com", "+7-999-111-22-33")  # TypeError

Переменное число аргументов с сохранением типа (typing.Protocol)

Для статической типизации произвольных аргументов можно определить протокол или использовать TypeVar, но это выходит за рамки основ.

Входные параметры в Python - comments

En
Python входные параметры (python)