为什么%s在连接方面比+好?


88

我知道我们应该使用%s连接字符串而不是+Python。

我可以执行以下任何一项操作:

hello = "hello"
world = "world"

print hello + " " + world
print "%s %s" % (hello, world)
print "{} {}".format(hello, world)
print ' '.join([hello, world])

但是我为什么要使用除之外的其他东西+呢?用简单的编写连接更快+。然后,如果你看一下格式化字符串,您指定的类型如%s%d和这样。据我了解,最好对类型进行明确说明。

但是后来我读到,+即使输入起来更容易,也应避免使用for串联。是否有明确的理由应该以其他方式之一将字符串连接起来?


29
谁告诉你更好?
yannis 2015年

3
%s不是用于串联,而是用于从C派生的字符串格式的转换规范printf(3)。在某些情况下,可以使用那个或一个串联运算符。您使用的信息应基于对情况的判断,而不是教条。编写代码的难易程度完全无关紧要,因为您只需要执行一次即可。
Blrfl 2015年

我将问题重新集中在 python上(尽管我不是python的人,并且代码中可能仍然存在故障)。请确保这是您要提出的问题,进行任何适当的更新,如果您对C或Java感兴趣,请考虑提出其他问题。

12
现在,我们有了上乘的F弦print(f"{hello} {world}"),具有连接的可读性,因为可以在字符串中的位置看到变量,并且比快str.format
恩里科·博尔巴

Answers:


88
  1. 可读性。格式字符串语法更具可读性,因为它可以将样式与数据分开。另外,在Python中,%s语法会自动将所有非str类型强制为str;;而串联只有工作str,你不能连接str使用int

  2. 性能。在Python中str是不可变的,因此对于每对串联,必须将左右字符串复制到新字符串中。如果连接四个长度为10的字符串,则将复制(10 + 10)+((10 + 10)+10)+((((10 + 10)+10)+10)= 90个字符,而不是40个字符字符。随着字符串的数量和大小增加,情况将变得更加糟糕。Java有时通过将一系列串联转换为use来优化这种情况StringBuilder,但是CPython却没有。

  3. 对于某些用例,日志记录库提供了一个API,该API使用格式字符串来懒惰地创建日志条目字符串(logging.info("blah: %s", 4))。如果日志记录库确定当前日志条目将被日志过滤器丢弃,那么这对于提高性能非常有用,因此不需要格式化字符串。


31
您是否有#1的科学或经验来源?因为我认为它的可读性差很多(尤其是带有两个或三个以上的参数)
Lovis

4
@L.Möller:我不太确定您从最终的主观体验(易于阅读)中期望什么样的来源,但是如果您要我的推理:1)%s每个占位符需要2个额外的字符,而+需要至少4个(如果遵循PEP8,则为8;如果您强制,则为13),2)%s包含在单个字符串中,因此使用+可以更直观地进行解析,您可以使用更多的移动部分:闭合字符串,运算符,变量,运算符,打开的字符串,3)语法着色%s为每种功能提供一种颜色:字符串和占位符,使用+可获得三种着色:字符串,运算符和可变着色。
Lie Ryan 2015年

4
@L.Möller:4)我可以选择将较长的格式字符串放在变量或字典中,而不需要进行格式化,5)可以从配置文件,命令args或数据库中指定格式字符串,不能用串联来表示。但是,是的,当要插入的内容超过4-5个时,我也不会使用%s,而是在Python中使用%(varname)s变体或“ {foo}”。format()。我认为显式名称提高了带有许多内插变量的较长格式字符串的可读性。
Lie Ryan

2
我不知道什么是“真实的”,这就是为什么我问你是否有证据:-)。真的同意您的第二条评论
Lovis 2015年

6
我发现#2值得怀疑-您有书面证明吗?我对Java并不是很熟悉,但是在C#中,串联比字符串插值要快。我完全同意#1并真的依靠它来决定何时使用它,但是您必须记住,插值需要大量的字符串解析和复杂性,而级联则不需要。
Jimmy Hoffa

48

我是唯一一个从左到右阅读的人吗?

对我而言,使用%s就像听德语,在这里我必须等到很长的句子结束才能听到动词是什么。

快速浏览以下哪个更清晰?

"your %s is in the %s" % (object, location)

要么

"your " + object + " is in the " + location  

17
显然,这是主观的,因为我发现第一个更具可读性-更加容易编写和编辑。第二种方法将文本与使两者混淆并增加噪音的代码混合在一起。例如,很容易在第二个地方弄错空格。
JacquesB '16

5
@JacquesB我实际上认为您的大脑非常熟悉这种格式,以至于您立即跳到方括号中并立即替换单词。从技术上讲,这不是从左到右的阅读,但这很好。我发现我也这样做,所以是的,1更容易阅读,因为我知道我必须处理第二个引号之前和之后的愚蠢间距问题,而且处理起来确实很慢。
尼尔森

3
经过n几十年来,我的心就像太;-)但我还是爱用我的回答立场,二是更清晰,更易于阅读,因此维持。参数越多,这一点就越明显。最后,如果是单人表演,那就去熟悉和熟悉的地方。如果是团队合作,请执行一致性检查和代码审查;人们可以习惯。
Mawg '16

4
第一个对我来说更具可读性,因为它在句子中间的“草皮”更少。我的眼睛看向末尾要容易得多,而脑中解析出多余的引号,空格和加号会更容易。当然,我现在更喜欢Python 3.6格式的字符串: f"your {object} is in the {location}"
Dustin Wyatt

8
当变量本身需要用引号引起来时,我也发现更难读写。 "your '" + object + "' is in the '" + location + "'"...我什至不确定我是否现在就知道了...
Dustin Wyatt

12

澄清可读性参数的示例:

print 'id: ' + id + '; function: ' + function + '; method: ' + method + '; class: ' + class + ' -- total == ' + total

print 'id: %s; function: %s; method: %s; class: %s --total == %s' % \
   (id, function, method, class, total)

(请注意,第二个示例不仅更具可读性,而且更易于编辑,您可以在一行上更改模板,而在另一行上更改变量列表)

一个单独的问题是%s代码也将转换为字符串,否则您必须使用str()调用,该调用也比%s代码可读性低。


1
我不同意您的第一句话,但我们可以同意有所不同,我正要按照您的第二
句话

6

使用+应该一般是可以避免的。在许多情况下是正确的方法。使用%s.join()仅在特定情况下才是首选,当它们是更好的解决方案时通常很明显。

在您的示例中,您将三个字符串串联在一起,使用示例+显然是最简单,最易读的,因此建议您这样做。

%s.format()在想要在较大字符串中间插入字符串或值时很有用。例:

print "Hello %s, welcome to the computer!" % name

在这种情况下,使用%s它更具可读性,因为避免将第一个字符串切成多个段。尤其是当您内插多个值时。

.join() 如果您具有可变大小的字符串序列和/或要使用相同的分隔符将多个字符串连接起来,则适用。


2

由于单词顺序可能会以不同的语言更改,因此%s如果您要在软件中正确支持字符串的翻译,则必须使用形式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.