Параметры функций в 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-расширениях).
Расширенные примеры использования типов параметров
# Пример 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}