Параметры функций в Python: полное описание с примерами

Раздел: Работа с функциями -> Функции

Использование различных типов параметров в Python

Наиболее эффективное решение: полное описание параметров с аннотациями типов

Применение аннотаций типов совместно с явным указанием позиционных и именованных параметров повышает читаемость кода, помогает статическим анализаторам (mypy, IDE) и снижает вероятность ошибок. Рекомендуется для всех новых проектов.


def connect(host: str, port: int = 8080, timeout: float | None = None) -> bool:
    """
    Устанавливает соединение с сервером.
    :param host: IP или домен
    :param port: порт (по умолчанию 8080)
    :param timeout: таймаут в секундах, None - без таймаута
    :return: True если соединение успешно
    """
    if timeout is not None:
        # логика с таймаутом
        pass
    return True

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

Здесь host - обязательный позиционно-ключевой параметр, port - необязательный с типом int, timeout - необязательный с типом float или None. Аннотации документируют ожидаемые значения.

Типичные ошибки:

  • Изменяемые объекты в качестве значений по умолчанию (например, list []). Проблема - один и тот же объект используется во всех вызовах. Решение: использовать None и создавать новый объект внутри функции.
  • Неправильный порядок параметров: сначала позиционные, потом со значением по умолчанию, затем *args, затем keyword-only, затем **kwargs. Нарушение порядка вызывает SyntaxError.

Как создать параметры, передаваемые только по ключу (keyword-only)?

Параметры, которые можно указывать только по имени, ставятся после * или после *args.

def process(data, *, encoding='utf-8', errors='strict'):
    # data можно передать позиционно или по имени
    # encoding и errors - только по имени
    pass

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

Проблема: если забыть *, все параметры станут позиционно-ключевыми. Используйте * для принудительного разделения.

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

*args собирает дополнительные позиционные аргументы в кортеж, **kwargs - именованные в словарь.

def log(message, *args, level='INFO', **kwargs):
    print(f"[{level}] {message}")
    if args:
        print(f"  Позиционные доп. аргументы: {args}")
    if kwargs:
        print(f"  Именованные доп. аргументы: {kwargs}")

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

Ошибка: часто путают порядок - **kwargs всегда должен быть последним. Также нельзя иметь несколько *args или **kwargs.

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

Используйте значение по умолчанию None и аннотацию Optional[тип] или тип | None. Внутри функции явно проверяйте на None.

def find_user(user_id: int, default_name: str | None = None) -> str:
    if default_name is None:
        default_name = "Гость"
    # поиск
    return default_name

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

Распространённая ошибка: использование =[] или ={} - изменяемый объект будет общим для всех вызовов.

Как зафиксировать, что параметр может быть только позиционным (positional-only)?

Параметры до символа / являются строго позиционными (доступны только по порядку).

def div(a, b, /):
    return a / b
# div(a=10, b=2) -> TypeError: div() got some positional-only arguments passed as keyword arguments

Такие параметры нельзя передавать по имени, что может быть неочевидно для вызывающего кода. Используйте с осторожностью, только когда это действительно нужно (например, в C-расширениях).

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

Расширенные примеры использования типов параметров

Пример

# Пример 1: комбинирование всех видов параметров с аннотациями
def advanced(a: int, b: str, /, c: float = 0.0, *args, d: bool = True, **kwargs) -> None:
    print(f"a={a}, b={b}, c={c}, d={d}")
    print(f"args={args}, kwargs={kwargs}")

advanced(1, 'hello', 3.14, 4, 5, key='val', d=False)
a=1, b=hello, c=3.14, d=False
args=(4, 5), kwargs={'key': 'val'}
Пример

# Пример 2: проблема изменяемого по умолчанию и её решение
def append_to(item, target=[]):
    target.append(item)
    return target

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

# Правильный вариант:
def append_to_fixed(item, target=None):
    if target is None:
        target = []
    target.append(item)
    return target
[1]
[1, 2]
Пример

# Пример 3: аннотации с Union (старый стиль) и новый синтаксис
from typing import Union, Optional

def old_style(x: Union[int, str]) -> None:
    pass

def new_style(x: int | str) -> None:
    pass

def optional_param(y: Optional[float] = None) -> float:
    return y if y is not None else 0.0
(без вывода, только демонстрация синтаксиса)
Пример

# Пример 4: использование keyword-only параметров для конфигурации
def run_command(cmd: str, *, timeout: int = 60, verbose: bool = False) -> str:
    import subprocess
    result = subprocess.run(cmd, shell=True, capture_output=True, timeout=timeout)
    if verbose:
        print(result.stdout.decode())
    return result.stdout.decode()

# Вызов: run_command("ls", timeout=10, verbose=True) - корректно
# run_command("ls", 10) -> TypeError
(вывод не показан, чтобы не вводить зависимость от ОС)
Пример

# Пример 5: позиционные-only параметры для сокрытия имён
def create_user(name: str, /, age: int):
    # name нельзя передать по имени, age можно
    return {'name': name, 'age': age}

user = create_user('Alice', age=30)  # OK
# user = create_user(name='Alice', age=30) -> TypeError
{'name': 'Alice', 'age': 30}

Тип параметра функции в Python - comments

En
Python тип параметра функции (python)