为什么 printf() 在 python 中给出了一个奇怪的输出?

Why is printf() giving a strange output in python?

我尝试在 Linux 上的 python 命令行中使用 C 函数 printf()。为了完成这项工作,我导入了 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
>>>

我猜不出是什么导致了这种行为...
如果重要的话,我在 Linux 上使用 Python 2.7.6。

编辑:

Python版本/操作系统对此没有影响。有关详细信息,请参阅下面 PM 2Ring 的回答。在 Windows 上,您只需将 libc 的初始化更改为 libc = ctypes.CDLL("msvcrt.dll"),其中 .dll 是可选的。另一种获得正确输出而不是调用函数的方法是将 printf() 的 return 值存储在变量中:

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

我还是更喜欢这个功能,因为你可以更容易地添加结束换行符。

每个数字末尾的额外 '1'printf 的 return 值,return 是它打印的字符数。在交互式解释器中调用的函数的 return 值会自动打印出来(除非它是 None)。

事实上,交互式解释器会打印任何未分配的非None 表达式。当然,它会为这些表达式添加换行符,这就解释了为什么第一个代码块中的输出在不同的行上。

您的 pr 函数没有 return 语句,因此它 return 是 None,因此不会打印额外的内容。

虽然 PM 2Ring 很好地回答了这个问题,但我认为值得指出的是 printf 的行为,或者非常接近的行为,可以作为 python 内置使用,所以你真的很奇怪将使用 C 库版本,除非您使用它来学习如何使用 ctypes,在这种情况下继续。

但另一方面,当你还没有足够地使用 python 来了解 REPL 的工作原理时想要使用 ctypes 是很奇怪的......冒着听起来傲慢的风险,作为一个拥有 10 年 python 经验的人,我实际上从未使用过 ctypes

python 中有两个用于字符串格式化的内置选项:

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

这是旧风格,与 printf 非常相似,并且

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

这是 python 3 的新功能,并且功能更强大。有questions addressing the differences on this site. Both of the above lines will output identically to libc.printf("%d\n", i). It's also possible to print without the newline.

"%" 字符串格式化的 CPython 实现实际上使用了 sprintf under the hood