Какой метод использует Python 2 для печати кортежей?
Оператор Python print
обычно печатает repr()
своего ввода. Кортежи не являются исключением:
>>> print (1, 2, 3)
(1, 2, 3)
>>> print repr((1, 2, 3))
(1, 2, 3)
Но затем я наткнулся на какое-то странное поведение, в то время как возился с внутренними CPython. Короче говоря: если вы обманываете Python 2 в создании саморегуляционного кортежа, его печать напрямую ведет себя совершенно иначе, чем печать его представлений repr()
/str()
/unicode()
.
>>> print outer # refer to the link above
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
... many lines later ...
((((((((((Traceback (most recent call last):
File "<stdin>", line 1, in <module>
MemoryError: stack overflow
>>> print repr(outer)
((...),)
>>> print str(outer)
((...),)
>>> print unicode(outer)
((...),)
Так что же делает print
? В попытке ответить на этот вопрос сам я упомянул ссылку на язык:
print
оценивает каждое выражение по очереди и записывает полученный объект в стандартный вывод (см. ниже). Если объект не является строкой, он сначала преобразуется в строку, используя правила для преобразования строк.
И правила для преобразования строк:
Преобразование строк - это список выражений, заключенный в обратном порядке (a.k.a. назад):
string_conversion ::= "`" expression_list "`"
Но включение outer
в обратные кавычки имеет тот же результат, что и вызов repr()
и друзей. Нет кубиков. Так что, черт возьми, print
действительно делает за кулисами?
(Интересно, что поведение "фиксировано" в Python 3: печать саморегуляторного кортежа дает усеченную форму с эллипсией.)
Ответы
Ответ 1
Вы можете узнать, что на самом деле происходит, разобрав байт-код python.
>>> from dis import dis
>>> dis(compile('print outer', '<string>', 'exec'))
1 0 LOAD_NAME 0 (outer)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
И чтение источника для базовых кодов операций.
PRINT_ITEM в конечном итоге достигает этого блока кода:
else if (Py_TYPE(op)->tp_print == NULL) {
PyObject *s;
if (flags & Py_PRINT_RAW)
s = PyObject_Str(op);
else
s = PyObject_Repr(op);
...
}
else
ret = (*Py_TYPE(op)->tp_print)(op, fp, flags);
Это означает, что __str__
или __repr__
будут вызываться, только если тип объекта не имеет функции tp_print. И tupleobject имеет один.
Если вы хотите понять внутренности CPython, лучший способ - прочитать исходный код. Я рекомендую серию руководств по внутренним элементам python, он объясняет все, что вы должны знать, чтобы полностью понять вывод функции python dis.