#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. Вы имеете в виду, что хотите перегрузить функциональность сборки
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