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

Раздел: Python -> Функции

Что такое аргументы функции и зачем они нужны

Аргументы (parameters) в Python - это данные, которые передаются функции при её вызове. Они позволяют делать функцию гибкой и переиспользуемой. В Python существует несколько способов объявления и передачи аргументов, каждый из которых подходит для определённых сценариев.

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

Наиболее эффективный способ - комбинировать позиционные аргументы, аргументы по умолчанию, а также использовать *args и **kwargs. Это позволяет создавать функции, которые могут обрабатывать как обязательные, так и необязательные данные.

def create_profile(name, age, *hobbies, **extra):
    """Создаёт словарь профиля пользователя."""
    profile = {
        'name': name,
        'age': age,
        'hobbies': list(hobbies) if hobbies else None
    }
    profile.update(extra)
    return profile

# Примеры вызова
print(create_profile('Alice', 30, 'reading', 'swimming', city='NYC', job='engineer'))
print(create_profile('Bob', 25))
print(create_profile('Charlie', 35, 'gaming', city='London'))

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

{
    'name': 'Alice',
    'age': 30,
    'hobbies': ['reading', 'swimming'],
    'city': 'NYC',
    'job': 'engineer'
}
{
    'name': 'Bob',
    'age': 25,
    'hobbies': None,
}
{
    'name': 'Charlie',
    'age': 35,
    'hobbies': ['gaming'],
    'city': 'London'
}

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

В этом примере name и age - обязательные позиционные аргументы. *hobbies собирает все переданные после них позиционные аргументы в кортеж. **extra собирает все именованные аргументы в словарь. Такая конструкция позволяет создавать очень гибкие API.

Типичная ошибка: попытка передать именованный аргумент до позиционного после распаковки *args. Python запрещает это, так как после *args все позиционные аргументы должны передаваться только по имени.

# Ошибка! Нельзя имя после *args
# create_profile('Alice', 30, 'hobbies', city='NYC')  # hobbies воспримется как часть *args

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

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

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

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

def greet(name, greeting='Привет'):
    return f'{greeting}, {name}!'

print(greet('Анна'))
print(greet('Пётр', 'Здравствуйте'))

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

Привет, Анна!
Здравствуйте, Пётр!

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

Ошибка: использование изменяемого объекта (список, словарь) в качестве значения по умолчанию. Значение по умолчанию вычисляется только один раз при определении функции, и все вызовы будут использовать один и тот же объект.

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

print(add_item('a'))
print(add_item('b'))  # Ожидаем ['b'], а получаем ['a', 'b']

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

['a']
['a', 'b']

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

Решение: использовать None и создавать новый объект внутри функции.

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

print(add_item('a'))
print(add_item('b'))

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

['a']
['b']

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

Как заставить передавать аргументы только по имени (keyword-only)?

После аргумента * (не путать с *args) все следующие аргументы становятся обязательными именованными.

def connect(host, port, *, timeout=10, ssl=True):
    print(f'Connecting to {host}:{port}, timeout={timeout}, ssl={ssl}')

connect('localhost', 8080)
connect('localhost', 8080, timeout=30, ssl=False)
# Следующий вызов вызовет ошибку
# connect('localhost', 8080, 30)  # TypeError: connect() takes 2 positional arguments but 3 were given

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

Connecting to localhost:8080, timeout=10, ssl=True
Connecting to localhost:8080, timeout=30, ssl=False

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

Это повышает читаемость кода и предотвращает случайную передачу неверного порядка.

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

Использование **kwargs позволяет функции принимать любые ключевые аргументы в виде словаря.

def show_config(**kwargs):
    for key, value in kwargs.items():
        print(f'{key} = {value}')

show_config(db_host='localhost', db_port=5432, debug=True)

Python передать аргументы (передача аргументов в python)

db_host = localhost
db_port = 5432
debug = True

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

Это удобно для конфигураций, обёрток и декораторов.

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

Аннотации не влияют на выполнение, но улучшают читаемость и помогают IDE и линтерам.

def calc_sum(numbers: list[int], start: int = 0) -> int:
    return start + sum(numbers)

result = calc_sum([1,2,3], 10)
print(result)

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

16

Современные инструменты (mypy, pyright) могут статически проверять типы.

- Python return value (возвращаемое значение функции в python)
- абсолютное значение python (абсолютное значение в python)
- вернуть значение функции python (возврат значения из функции в python)

Расширенные примеры работы с аргументами

Комбинирование всех видов аргументов в одной функции

Пример
def register_user(
        username: str,
        email: str,
        *groups: str,
        is_active: bool = True,
        **extra: any
) -> dict:
    """Регистрирует пользователя с группами и дополнительными полями."""
    user = {
        'username': username,
        'email': email,
        'groups': list(groups),
        'active': is_active
    }
    user.update(extra)
    return user

# Вызов с разными наборами аргументов
user1 = register_user('ivan', 'ivan@example.com', 'admins', 'users', is_active=False)
user2 = register_user('maria', 'maria@example.com', 'vip', phone='+12345', age=30)
user3 = register_user('guest', 'guest@example.com')

print(user1)
print(user2)
print(user3)
{
    'username': 'ivan',
    'email': 'ivan@example.com',
    'groups': ['admins', 'users'],
    'active': False
}
{
    'username': 'maria',
    'email': 'maria@example.com',
    'groups': ['vip'],
    'active': True,
    'phone': '+12345',
    'age': 30
}
{
    'username': 'guest',
    'email': 'guest@example.com',
    'groups': [],
    'active': True
}

Обратите внимание: *groups собирает все позиционные аргументы, переданные после email, в кортеж. Если передать только обязательные, кортеж будет пуст. Именованный is_active имеет значение по умолчанию, но может быть переопределён. **extra принимает любые дополнительные именованные аргументы.

Распаковка аргументов из последовательностей и словарей

Пример
def point(x, y, z):
    return f'Point({x}, {y}, {z})'

# Распаковка списка/кортежа
coords = [10, 20, 30]
print(point(*coords))

# Распаковка словаря (ключи должны совпадать с именами параметров)
data = {'x': 100, 'y': 200, 'z': 300}
print(point(**data))

# Смешанная распаковка
base = (1, 2)
extra = {'z': 3}
print(point(*base, **extra))
Point(10, 20, 30)
Point(100, 200, 300)
Point(1, 2, 3)

Распаковка часто используется при передаче динамических наборов данных в функции. Ошибка возникает, если количество элементов не совпадает с количеством параметров или ключи не соответствуют именам.

Аргументы только по ключу (keyword-only) с *args

Пример
def process_data(*items, separator=', ', prefix='data:'):
    """Объединяет элементы с разделителем и префиксом."""
    result = separator.join(str(item) for item in items)
    return f'{prefix}{result}'

print(process_data(1, 2, 3))
print(process_data('a', 'b', 'c', separator=' - ', prefix='Result: '))
data:1,2,3
Result: a - b - c

Здесь separator и prefix могут быть переданы только по имени, так как они находятся после *items. Это предотвращает путаницу: если бы separator был третьим позиционным, его можно было бы случайно передать как элемент.

Использование аргументов по умолчанию с замыканиями

Пример
def power_factory(exponent):
    def power(base, exp=exponent):
        return base ** exp
    return power

square = power_factory(2)
cube = power_factory(3)

print(square(5))
print(cube(5))
# Можно переопределить экспоненту
print(square(5, exp=3))
25
125
125

Значение по умолчанию для exp фиксируется во время определения внутренней функции. Это удобно для создания параметризованных функций.

Аргументы и декораторы

Пример
def debug(func):
    def wrapper(*args, **kwargs):
        print(f'Calling {func.__name__} with args={args}, kwargs={kwargs}')
        result = func(*args, **kwargs)
        print(f'Result: {result}')
        return result
    return wrapper

@debug
def multiply(x, y):
    return x * y

multiply(3, 4)
multiply(x=5, y=6)
Calling multiply with args=(3, 4), kwargs={}
Result: 12
Calling multiply with args=(), kwargs={'x': 5, 'y': 6}
Result: 30

Декоратор debug принимает любые аргументы исходной функции и передаёт их дальше. Это стандартный шаблон для обёрток.

Типичные проблемы с изменяемыми аргументами по умолчанию (глубокое копирование)

Пример
def bad_default(items=[]):
    items.append(1)
    return items

# Первый вызов
print(bad_default())
print(bad_default())

# Правильное решение
from typing import List, Optional

def good_default(items: Optional[List[int]] = None) -> List[int]:
    if items is None:
        items = []
    items.append(1)
    return items

print(good_default())
print(good_default())
print(good_default([0]))
[1]
[1, 1]
[1]
[1]
[0, 1]

Видно, что bad_default накапливает элементы, тогда как good_default каждый раз создаёт новый список, если не передан аргумент.

Аннотации типов и проверка с помощью pydantic (расширенный пример)

Пример
from pydantic import BaseModel
from typing import List, Optional

class User(BaseModel):
    name: str
    age: int
    hobbies: List[str] = []
    
def create_user(data: User) -> dict:
    return data.dict()

# Валидация происходит при создании объекта User
user = User(name='Anna', age=25, hobbies=['reading', 'coding'])
print(create_user(user))

# Попытка передать неверный тип вызовет исключение
# User(name='Bob', age='abc')  # validation error
{'name': 'Anna', 'age': 25, 'hobbies': ['reading', 'coding']}

Это демонстрирует, как аннотации аргументов можно дополнить библиотеками для строгой валидации.

Аргументы метода Python - comments

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