Определение собственной функции 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с переносом'

Полезно при отладке, чтобы видеть невидимые символы.

Определение функции print в Python - comments

En
Def print python (python)