Ориентировочные печати на Python

#python

#python

Вопрос:

Я бы хотел, чтобы был какой-то способ генерировать более ориентировочные отпечатки на python: при печати некоторого значения будет распечатан не только результат, но и выражение, которое дало мне этот результат.

Например, допустим, у меня есть:

 >>> x = 1
  

Тогда для печати x и его типа мы получаем:

 >>> print x ; print type(x)
1
<type 'int'>
  

Я хотел бы получить что-то вроде:

 >>> print x ; print type(x)
x: 1
type(x): <type 'int'>
  

Я пробовал использовать locals (), модуль inspect, но я не смог получить этот результат.
Любой идентификатор
Спасибо.

Комментарии:

1. Вы имеете в виду, что хотите перегрузить функциональность сборки print ?

2. Я не думаю, что вы можете напрямую перегрузить print, поскольку это оператор, а не метод (следовательно, почему ему не нужны скобки). Однако вы могли бы перегрузить запись в sys.stdout.

3. на всякий случай: отладка выполняется с помощью отладчиков, а не печати.

Ответ №1:

Вы, конечно, можете написать функцию для этой цели:

 def print_ex(expr, globals=None, locals=None):
    res = eval(expr, globals, locals)
    print expr   ":", res
    print "type("   expr   "):", type(res)
  

Пример:

 >>> print_ex("2   3")
2   3: 5
type(2   3): <type 'int'>
  

Обратите внимание, что eval() выполняет произвольные выражения, поэтому убедитесь, что вы никогда не передаете строку из ненадежного источника в print_ex() .

Если вам не нравится необходимость явно передавать locals() и globals() , вы также можете использовать

 frame = inspect.currentframe().f_back
globals = frame.f_globals
locals = frame.f_locals
  

для автоматического использования globals() и locals() вызывающего фрейма.

Комментарии:

1. eval не является «изначально небезопасным». eval — это всего лишь инструмент, и он небезопасен только при использовании для запуска ненадежного кода. Существуют законные способы использования eval, которые полностью безопасны.

2. Этот мне тоже нравится. Лично я бы добавил необязательный аргумент с пространством имен для eval как в моем ответе, чтобы вы могли делать print_ex('a', locals()) для работы с именами переменных.

3. @Брайан: Да, спасибо. Мне было лень объяснять, в чем именно проблема eval() , но я чувствовал, что мне нужно как-то предупредить об этом. Ну, на SO вам никогда не сойдет с рук такое отношение … 🙂

Ответ №2:

Это демонстрирует наиболее разумный способ, который я могу придумать, чтобы легко отобразить нужную вам информацию:

 def info(name, namespace):
    thing = namespace[name]
    print "%s: %s" % (name, thing)
    print "type(%s): %s" % (name, type(thing))
  

Чтобы использовать его, укажите имя интересующего вас объекта и пространство имен:

 $ python -i info.py 
>>> a = 1
>>> info('a', locals())
a: 1
type(a): <type 'int'>
>>> 
  

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

Ответ №3:

Вы могли бы создать свою собственную функцию:

 def detailed_printer(expression):
    result = eval(expression)
    print(expression ": " str(result))
    return result
  

(Таким образом, вы также можете получить результат из возвращаемого значения)

* синтаксис python 3