快速但可能是愚蠢的问题。当我需要连接文本和数值以进行输出时,我通常会使用:
number = 4
print("Two plus two = " + str(number))
但有时我会看到:
number = 4
print("Two plus two =",number)
第二个示例不需要类型转换并添加前导空格,但除此之外它们做同样的事情。任何人都知道为什么有两种方法可以做同样的事情?哪种方法“更好”?
最佳答案
重要的是要理解 print("Two plus two = "+ str(number))
中的连接操作与 print
无关并且发生在之前print
被调用。
让我们做一些计时:
from timeit import Timer
def with_concat():
print("Two plus two = " + str(4))
def no_concat():
print("Two plus two =", 4)
print(min(Timer(with_concat).repeat(100, 100)))
print(min(Timer(no_concat).repeat(100, 100)))
输出
0.0006760049999998685
0.0013034899999999627
与直觉相反(请参阅我对问题的评论,字符串连接可能很昂贵)连接示例实际上以可重现的方式更快(2 倍!)。但是为什么?
让我们检查字节码:
from dis import dis
def with_concat():
print("Two plus two = " + str(4))
def no_concat():
print("Two plus two =", 4)
dis(with_concat)
输出
0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('Two plus two = ')
4 LOAD_GLOBAL 1 (str)
6 LOAD_CONST 2 (4)
8 CALL_FUNCTION 1
10 BINARY_ADD
12 CALL_FUNCTION 1
14 POP_TOP
16 LOAD_CONST 0 (None)
18 RETURN_VALUE
同时
dis(no_concat)
输出
0 LOAD_GLOBAL 0 (print)
2 LOAD_CONST 1 ('Two plus two =')
4 LOAD_CONST 2 (4)
6 CALL_FUNCTION 2
8 POP_TOP
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
从字节码来看,no_concat
应该更快(更短、更简单的代码)。
延迟必须来自 C 源代码(至少在 CPython 的情况下)。
让我们看看相关的行:
static PyObject *
builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
{
.
.
.
for (i = 0; i < PyTuple_Size(args); i++) {
if (i > 0) {
if (sep == NULL)
err = PyFile_WriteString(" ", file);
else
err = PyFile_WriteObject(sep, file,
Py_PRINT_RAW);
if (err)
return NULL;
}
err = PyFile_WriteObject(PyTuple_GetItem(args, i), file,
Py_PRINT_RAW);
if (err)
return NULL;
}
.
.
.
}
对我来说,使用 print(*args)
的开销似乎是由于重复调用 PyTuple_GetItem(args, i)
,而好处是在 print(a + lot + of + concatenated + strings)
上使用它只有当连接的字符串数量大到足以使连接成为瓶颈时(即比重复调用慢 PyTuple_GetItem(args, i)
).
关于python - 打印输出时 , 和 + 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52354518/