Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Зачем нужен *args?
*args используется в Python для передачи переменного количества позиционных аргументов функции. Это один из самых полезных инструментов при написании гибких и масштабируемых функций.
Основная концепция
*args преобразует все переданные позиционные аргументы в кортеж (tuple):
def print_all(*args):
print(f"Тип: {type(args)}")
print(f"Значение: {args}")
for i, arg in enumerate(args):
print(f" arg[{i}] = {arg}")
print_all() # args = ()
print_all(1) # args = (1,)
print_all(1, 2, 3) # args = (1, 2, 3)
print_all("hello", 42, [1, 2, 3]) # args = ("hello", 42, [1, 2, 3])
1. Функции с переменным количеством аргументов
# ❌ Плохо — ограничено 3 параметрами
def sum_two(a, b):
return a + b
sum_two(1, 2) # OK
sum_two(1, 2, 3) # TypeError!
# ✅ Хорошо — работает с любым количеством
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
sum_all(1, 2) # 3
sum_all(1, 2, 3, 4, 5) # 15
sum_all() # 0
2. Проксирование аргументов другой функции
Частый случай при создании декораторов и обёрток:
# Функция, которую мы хотим обернуть
def calculate(a, b, operation='add'):
if operation == 'add':
return a + b
elif operation == 'multiply':
return a * b
# Декоратор с логированием
def log_calls(func):
def wrapper(*args, **kwargs):
print(f"Вызов функции {func.__name__}")
print(f" Аргументы: {args}")
print(f" Ключевые аргументы: {kwargs}")
result = func(*args, **kwargs) # Передаём все как есть
print(f" Результат: {result}")
return result
return wrapper
@log_calls
def calculate(a, b, operation='add'):
if operation == 'add':
return a + b
elif operation == 'multiply':
return a * b
calculate(5, 3) # Работает
calculate(5, 3, operation='multiply') # Также работает
3. Функции форматирования и логирования
# Встроенная функция print использует *args
print("Hello", "World", 42, True) # print(*args)
# Эквивалентно:
print(("Hello", "World", 42, True))
# Пример: функция для логирования
def log_info(prefix, *messages):
"""Логировать сообщения с префиксом"""
output = f"[{prefix}] "
output += " | ".join(str(msg) for msg in messages)
print(output)
log_info("INFO", "Application started")
log_info("ERROR", "File not found", "Path: /etc/config.txt", "Code: 404")
log_info("DEBUG", "a", "b", "c", "d", "e") # Любое количество
4. Распаковка списков и кортежей
# Распаковка при вызове функции
def greet(first, second, third):
print(f"{first} {second} {third}")
names = ["Alice", "Bob", "Charlie"]
greet(*names) # Распаковка списка в аргументы
# Эквивалентно: greet("Alice", "Bob", "Charlie")
# Практический пример:传递данные между функциями
def get_user_data():
return "John", 30, "john@example.com"
def display_user(name, age, email):
print(f"{name}, {age} лет, {email}")
data = get_user_data()
display_user(*data) # Распаковка кортежа
5. Конкатенация аргументов
def concatenate(*args, separator=" "):
"""Объединить аргументы с разделителем"""
return separator.join(str(arg) for arg in args)
concatenate("Hello", "World") # "Hello World"
concatenate("a", "b", "c", separator="-") # "a-b-c"
concatenate(1, 2, 3, separator=",") # "1,2,3"
6. Создание функций с гибкой сигнатурой
class Logger:
def __init__(self, prefix):
self.prefix = prefix
def log(self, *messages, level="INFO"):
"""Логировать с любым количеством сообщений"""
full_message = " ".join(str(msg) for msg in messages)
print(f"[{self.prefix}] [{level}] {full_message}")
def debug(self, *messages):
self.log(*messages, level="DEBUG")
def error(self, *messages):
self.log(*messages, level="ERROR")
# Использование
logger = Logger("APP")
logger.log("Server started", "listening on port 8000")
logger.debug("Variable x =", 42, "Variable y =", 3.14)
logger.error("Connection failed", "Host unreachable", "Retry in", 5, "seconds")
7. Работа с matplotlib и другими библиотеками
Много популярных библиотек используют *args:
import matplotlib.pyplot as plt
# matplotlib.plot использует *args для нескольких линий
x = [1, 2, 3, 4]
y1 = [1, 4, 2, 3]
y2 = [2, 3, 4, 1]
y3 = [3, 2, 1, 4]
plt.plot(x, y1, label='Line 1')
plt.plot(x, y2, label='Line 2')
plt.plot(x, y3, label='Line 3')
# Или так:
plt.plot(x, y1, x, y2, x, y3)
# Эквивалентно вызову с *args внутри
def plot(*args, **kwargs):
for i in range(0, len(args), 2):
print(f"Линия {i//2}: {args[i]} -> {args[i+1]}")
8. Функции со звёздочкой в разных позициях
# ✅ Звёздочка в начале
def func1(*args):
print(args)
func1(1, 2, 3) # (1, 2, 3)
# ✅ Звёздочка с обычными параметрами
def func2(first, *args):
print(f"First: {first}, Rest: {args}")
func2(1, 2, 3, 4) # First: 1, Rest: (2, 3, 4)
# ✅ Звёздочка с именованными параметрами (именованные ПОСЛЕ *args)
def func3(*args, prefix="DEFAULT"):
print(f"Prefix: {prefix}, Args: {args}")
func3(1, 2, 3, prefix="CUSTOM") # Prefix: CUSTOM, Args: (1, 2, 3)
# ✅ Когда нужны обязательные параметры после *args
def func4(a, b, *args, separator="-"):
print(f"a={a}, b={b}, rest={args}, sep={separator}")
func4(1, 2, 3, 4, 5, separator="_") # a=1, b=2, rest=(3, 4, 5), sep=_
9. Сравнение *args и **kwargs
# *args — позиционные аргументы (кортеж)
# **kwargs — именованные аргументы (словарь)
def flexible(*args, **kwargs):
print(f"args: {args}")
print(f"kwargs: {kwargs}")
flexible(1, 2, 3) # args: (1, 2, 3), kwargs: {}
flexible(a=1, b=2) # args: (), kwargs: {'a': 1, 'b': 2}
flexible(1, 2, a=3, b=4) # args: (1, 2), kwargs: {'a': 3, 'b': 4}
# Практический пример
def create_request(*args, **kwargs):
"""Создать HTTP запрос с любыми параметрами"""
return {
"positional": args,
"keyword": kwargs
}
request = create_request("GET", "https://api.example.com", timeout=5, retries=3)
print(request)
# {'positional': ('GET', 'https://api.example.com'), 'keyword': {'timeout': 5, 'retries': 3}}
10. Вложенные функции с *args
def outer_function(*args):
def inner_function():
return sum(args) # Доступ к args из внешней функции
return inner_function
# Использование
f = outer_function(1, 2, 3, 4, 5)
print(f()) # 15
11. Анти-паттерны
# ❌ Плохо — путаница с семантикой
def confusing_function(*args):
a = args[0] # Неясно, что это должно быть
b = args[1] # Хрупкий код
c = args[2]
return a + b + c
# ✅ Хорошо — ясная семантика
def clear_function(a, b, c):
return a + b + c
# ✅ Или если нужна гибкость
def flexible_function(*numbers):
if len(numbers) < 3:
raise ValueError("Нужно минимум 3 параметра")
return sum(numbers[:3])
# ❌ Плохо — неинформативное использование *args
def mystery_function(*args):
return args[0] * args[1] + args[2] / args[3]
# ✅ Хорошо — документируем
def calculate_formula(numerator, *denominators):
"""Разделить numerator на произведение всех denominators"""
result = numerator
for denom in denominators:
result /= denom
return result
Выводы
*args используется для:
- Переменного количества параметров (print, max, min)
- Проксирования аргументов (декораторы, обёртки)
- Распаковки последовательностей (list, tuple)
- Гибких функций форматирования (логирование, строки)
- API, где не известно заранее количество параметров
Ключевая идея: используй *args когда аргументы однородны и их количество может варьироваться. Если аргументы разных типов и фиксированного количества, явно опиши параметры функции.