Определение собственной функции print в Python: примеры и нюансы
Определение собственной функции с именем print в Python
Как переопределить встроенную функцию print без рекурсии?
Наиболее надёжный способ переопределить print – создать свою функцию с тем же именем, но внутри неё вызывать оригинальную версию через модуль builtins. Это позволяет избежать бесконечной рекурсии, когда новая функция вызывает саму себя.
import builtins
def print(*args, sep=' ', end='\n', **kwargs):
# добавление префикса к каждому выводу
builtins.print('[LOG]', *args, sep=sep, end=end, **kwargs)Def f python (определение функции f в python)
Проблема:
Если внутри новой функции вызвать print() напрямую, начнётся бесконечная рекурсия, так как глобальное имя теперь указывает на вашу же функцию. Всегда используйте builtins.print() для делегирования оригинальному выводу.Цель: Глобально изменить поведение вывода во всём приложении, например, для добавления логирования или форматирования.
Как добавить временную метку к каждому выводу print?
import builtins
from datetime import datetime
def print(*args, sep=' ', end='\n', **kwargs):
timestamp = datetime.now().strftime('%H:%M:%S')
builtins.print(f'[{timestamp}]', *args, sep=sep, end=end, **kwargs)Def print python (определение функции print в python)
Теперь каждый вызов print() будет автоматически добавлять текущее время в начале строки.
Ошибка:
Если забыть импортировать datetime, возникнет NameError.Как направить вывод print в файл вместо консоли?
import builtins
import sys
default_file = open('output.log', 'a', encoding='utf-8')
def print(*args, sep=' ', end='\n', file=sys.stdout, **kwargs):
# если файл не указан явно, пишем в лог-файл
if file is sys.stdout:
file = default_file
builtins.print(*args, sep=sep, end=end, file=file, **kwargs)
Все сообщения, отправленные без явного указания file, будут записываться в лог-файл.
Проблема:
Файл остаётся открытым всё время. Необходимо предусмотреть его закрытие при завершении программы, иначе данные могут потеряться.Как сделать условный вывод (только при отладке)?
import builtins
DEBUG = True # флаг для включения/отключения
def print(*args, sep=' ', end='\n', **kwargs):
if DEBUG:
builtins.print(*args, sep=sep, end=end, **kwargs)
При DEBUG = False все вызовы print() будут игнорироваться. Удобно для продакшен-среды.
Ошибка:
Неявное подавление исключений - если внутри builtins.print() возникнет ошибка, она будет проигнорирована при выключенном DEBUG.Как изменить глобальный разделитель или концовку у всех print?
import builtins
def print(*args, sep=' | ', end=' \n', **kwargs):
builtins.print(*args, sep=sep, end=end, **kwargs)
Такая функция будет выводить элементы, разделённые символом ' | ', а после последнего элемента добавлять ' <end>'.
Замечание:
Если какой-либо код явно передаёт собственные sep или end, они будут переопределены. В реальных проектах стоит передавать их как параметры в новую функцию, а не зашивать константами.Расширенные примеры переопределения print
1. Декоратор для временного изменения print
import builtins
from functools import wraps
def override_print(prefix=''):
original_print = builtins.print
@wraps(original_print)
def new_print(*args, **kwargs):
original_print(prefix, *args, **kwargs)
return new_print
# Использование временного переопределения в контексте
builtins.print = override_print('[CONTEXT]')
print('Сообщение внутри контекста') # Выведет: [CONTEXT] Сообщение внутри контекста
[CONTEXT] Сообщение внутри контекста
После выхода из контекста оригинальный print не восстанавливается автоматически; это делается вручную.
2. Context manager для временного переопределения
import builtins
from contextlib import contextmanager
@contextmanager
def custom_print(prefix=''):
original = builtins.print
def new_print(*args, **kwargs):
original(prefix, *args, **kwargs)
builtins.print = new_print
try:
yield
finally:
builtins.print = original
# Использование
with custom_print('[PREFIX]'):
print('Привет')
print('Мир')
print('Вне контекста')
[PREFIX] Привет [PREFIX] Мир Вне контекста
Этот подход гарантирует восстановление исходной функции после выхода из блока with.
3. Print с уровнями логирования (info, error, debug)
import builtins
import sys
LOG_LEVEL = 'info'
def print(level='info', *args, **kwargs):
levels = {'info': 1, 'error': 2, 'debug': 3}
if levels.get(level, 0) < levels.get(LOG_LEVEL, 1):
return
prefix = f'[{level.upper()}]'
builtins.print(prefix, *args, **kwargs)
# Примеры вызовов
print('error', 'Критическая ошибка')
print('debug', 'Отладочная информация') # не выведется, если LOG_LEVEL='error'
[ERROR] Критическая ошибка
Функция принимает первым аргументом уровень, что ломает совместимость с обычным print, но даёт гибкость.
4. Print с отправкой данных по сети (UDP)
import builtins
import socket
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_addr = ('localhost', 9999)
def print(*args, **kwargs):
# Формируем строку для отправки
msg = ' '.join(str(a) for a in args) + kwargs.get('end', '\n')
udp_sock.sendto(msg.encode('utf-8'), udp_addr)
# Одновременно выводим на консоль, если нужно
builtins.print(*args, **kwargs)
# При вызове print строка отправляется на UDP-порт 9999 и выводится в консоль.
print('Тестовое сообщение')
Тестовое сообщение
Такой подход позволяет дублировать вывод в удалённый лог-сервер.
5. Print с автоматическим экранированием спецсимволов
import builtins
def print(*args, sep=' ', end='\n', **kwargs):
escaped_args = [repr(arg) if isinstance(arg, str) else arg for arg in args]
builtins.print(*escaped_args, sep=sep, end=end, **kwargs)
print('Строка\nс переносом') # Выведет экранированную строку с буквальными символами \n
'Строка\nс переносом'
Полезно при отладке, чтобы видеть невидимые символы.