Python-打印输出时,和+之间的区别

时间:2018-09-16 13:16:57

标签: python string comma

快速且可能是愚蠢的问题。当我需要连接文本和数字值以进行输出时,通常会使用:

number = 4
print("Two plus two = " + str(number))

但有时我会看到:

number = 4
print("Two plus two =",number)

第二个示例不需要类型转换,并且添加了前导空格,但是否则它们执行相同的操作。有人知道为什么有两种方法可以做同一件事吗?哪种方法“更好”?

2 个答案:

答案 0 :(得分:5)

重要的是要了解,在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)的重复调用)。

答案 1 :(得分:0)

正如@DeepSpace所评论的那样,使用+运算符连接字符串,使用两个参数仅使用 sep 参数作为分隔符(默认为空白)来逐一打印字符串。 有关更多信息,您可以检查Python 3.4 source code