Подтвердить что ты не робот

Почему printf() дает странный вывод в python?

Я попытался использовать C-функцию printf() в командной строке python в Linux. Чтобы выполнить эту работу, я импортировал ctypes. Моя проблема: если я создаю объект CDLL для использования printf() -функции в цикле, я получаю действительно странный вывод:

>>> import ctypes
>>> libc = ctypes.CDLL("libc.so.6")
>>> for i in range(10):
...     libc.printf("%d", i)
...
01
11
21
31
41
51
61
71
81
91
>>>

Однако, когда я вызываю этот цикл внутри функции, он работает как ожидалось:

>>> import ctypes
>>> libc = ctypes.CDLL("libc.so.6")
>>> def pr():
...     for i in range(10):
...         libc.printf("%d", i)
...     libc.printf("\n")
...
>>> pr()
0123456789
>>>

Я не могу догадаться, что вызывает такое поведение...
Я использую Python 2.7.6 для Linux, если это имеет значение.

EDIT:

Версия Python/операционная система не влияет на это. См. Ниже приведенный комментарий PM 2Ring. В Windows вам нужно изменить инициализацию libc на libc = ctypes.CDLL("msvcrt.dll"), где .dll является необязательным. Другой способ получить правильный результат, чем вызов функции, - сохранить возвращаемое значение printf() в переменной:

>>> import ctypes
>>> libc = ctypes.CDLL("libc.so.6")  # "mscvrt.dll" on windows
>>> for i in range(10):
...     r = libc.printf("%d", i)
...
0123456789>>>

Я по-прежнему предпочитаю эту функцию, потому что вы можете добавить завершающую линейку.

4b9b3361

Ответ 1

Эти дополнительные '1' в конце каждого числа - это возвращаемое значение из printf, которое возвращает количество символов, которые он печатает. Возвращаемое значение функции, вызываемой в интерактивном интерпретаторе, автоматически печатается (если только None).

Фактически, интерактивный интерпретатор печатает любое выражение не None, которое не назначено. И, конечно же, он добавляет новую строку в эти выражения, что объясняет, почему вывод в вашем первом блоке кода находится в отдельных строках.

В вашей функции pr нет оператора return, поэтому он возвращает None, и, таким образом, никакие дополнительные материалы не будут напечатаны.

Ответ 2

В то время как PM 2Ring ответил на вопрос достаточно хорошо, я считаю, что стоит отметить, что поведение printf или что-то очень близкое, доступно как встроенный python, поэтому очень странно, что вы будете использовать C версию библиотеки, если вы не используете ее, чтобы узнать, как использовать ctypes, и в этом случае продолжить.

Но, с другой стороны, странно хотеть использовать ctypes, когда вы не использовали достаточно питона для того, чтобы знать, как работает REPL... рискует казаться высокомерным, как человек с 10-летним опытом питона, Мне никогда не приходилось использовать ctypes.

Есть два встроенных параметра форматирования строк в python:

print("%d" % (i,))

который является старым стилем и очень похож на printf, и

print("{:d}".format(i))

который является новым для python 3 и несколько более мощным. Есть questions, где рассматриваются различия на этом сайте. Обе вышеперечисленные строки будут выводиться идентично libc.printf("%d\n", i). Также можно печатать без новой строки.

Реализация форматирования строк "%" на CPython фактически использует sprintf под капотом.