Python 字符串应该用双引号还是单引号?
PyCharm升级至 2023.2版本后,经常弹出来一个提示问我要不要试一下Black formatter。
试了一下,这个Black formatter 很有个性,特别喜欢换行。我的一个文件用PyCharm自带的代码整理器整理完之后是500行左右,然后再用Black整理就变成600多行了。
原来Black是Python Software Foundation主导的开源项目,Python亲儿子,口号也很有个性:The uncompromising Python code formatter。
它的Uncompromising还体现在它github上的第118个issue,2018年提出,是一个讨论了上百楼的神贴。
他们讨论的问题是:字符串应该用双引号还是单引号。
提问者的诉求
Python的字符串既允许双引号也允许单引号,甚至允许三引号。这种灵活性自然引起群魔乱舞,特别是双引号和单引号,大家基本上有自己的喜好。然而Black毫不妥协,规定只能用双引号。
提问者bofm 手上维护着一些更喜欢用单引号的旧项目,他问能不能提供一个选项让用户保留单引号。
他列出了一些理由:
-
存量项目已经采用单引号规则。
-
Python官方文档例子都用单引号。
-
repr() 返回单引号。
-
很多著名项目都用单引号
-
PEP 的例子大多数用单引号。
-
Guido(Python之父)在他最新的github commits里使用单引号。
强硬拒绝
事实上,作者还未出来,另外一个用户就已经点灭这个issue,他说Black的优点就是消灭掉这些鸡毛蒜皮的选择。接着Black的第一作者出来了。这位第一作者Lukasz Langa 是大神,Python核心团队成员,波兰人,钢琴家。
他(github账号是ambv)认为bofm说的理由都不是理由,就相当于说"由于其他项目无原则,所以Black也不应该有原则"。这种盲从权威(an appeal to authority)的做人态度是不行的,Black是uncompromising的,绝不妥协。况且存量项目仍然可以用,只是可能看不惯格式化后的代码。
惨遭封贴
这时有个人出来帮bofm说话,他说技术上很容易满足bofm的需求,black已经提供了每行字数的选项,再加一个选项很容易,如果官方不肯加,那就Fork一个分支自己干。
这最后一句话可能激怒了ambv,他说虽然MIT协议允许你们随便fork单干,但在我的帖子里提到fork我会感到被冒犯,希望以后不要再提。
ambv说作为一个标准化格式化工具,太多的选择对用户来说反而是一个负担,也会使用户进一步要求更多选择(正如上面那个人提到的,既然提供每行字数的选项,为什么不能再加一个选项)。ambv 强调一定要标准化,反而不怎么关心究竟是双引号还是单引号更好,反正选其中一个就行。在决定使用哪个引号之前,他曾经和carljm和zsol 商议,他们说服了他双引号更好,所以最终用双引号。
ambv还反驳了在键盘上更容易敲打单引号的论据,他认为你喜欢打单引号就只管打,反正最后Black一键帮你转成双引号,毫不费力。
说完,ambv就暂时关闭了这个issue,说如果有更充分的理由,他会重新打开。这时距离这个帖子的诞生只过了3天。
激烈讨论
尽管issue暂时被关闭,但各路人马仍然蜂拥而至表达自己的观点。其中有一位叫alanhamlett的仁兄语气比较冲。
前面提到ambv说他咨询过carljm和zsol的意见才选择了双引号,alanhamlett上来就直接@zsol 问他为什么双引号比单引号更好。ambv见到有人在自己的地盘绕开他,分明是不把他放在眼内,于是反问alanhamlett:README里的解释还不够吗?
岂料alanhamlett直接开大。他说:对,那个解释就是不够。你应该遵循Prettier's example 允许用户选择用哪个引号,而不是把大量开发团队拒之门外。他还补充到,这个话题太鸡毛蒜皮(bikeshedding)了,作者接受群众意见允许选择就完事了,婆婆妈妈干什么(婆婆妈妈是我加上去的)。
ambv当然要马上还击。他提醒alanhamlett注意言辞,就算你的观点是对的,但你说话的方式仍然很难让别人接受。下面是他的教训环节:
仅仅因为你不同意另一方的观点,就说一个话题幼稚,这只会令事态升级。指责我把"大量开发团队拒之门外"是夸张和不公平的。指导我们这些用爱发电的开源项目作者"该做什么"是很傲慢的。你是局外人,没资格要求任何东西。
ambv总结了他的观点:Black是PEP 8规范的子集,定义很清晰。Black永远不会提供"使用单引号代替双引号"的选项,因为这违背了Black的标准化原则,一旦开了允许选择的先例就无法收拾。他考虑的是是否允许"不强制单引号转成双引号"(即bofm一开始的诉求:保留单引号)。他表示对此话题保持开放态度,但担心以后越来越多豁免这豁免那的要求。这和Black的强迫症原则有冲突。
这时有个叫audiolion的人火上加油。他说他曾经很欣赏black这个项目,但强制单转双这点不能忍,如果black不改变的话,他永远不会使用black,也不会向宣传black。他认为没有任何论据能够令ambv回心转意,但还是劝告ambv提供选择,这样会使大家都满意。
如果你不改,我保证有人会fork一个版本帮你改掉,其他功能都保持一致。这不是要篡夺你的王座,只是为与你观点不同的人提供一个选择。
很奇怪,这次ambv没有回喷,只是默默地重新打开了这个issue。这时距离帖子诞生日差不多两个月。
观点整理
这时候有个叫zestyping的重量级人物出来了。他在Hacker News那边就参加过这个议题,现在跟到这边吃瓜。他说希望贡献自己的一份力量(更重要的原因是周六晚上没事干),就把帖子里的各方观点整理一遍,尽量中立地展示各种论据。他还很贴心地按照"来源"和"类别"两个大方向组织论据。这里按类别展示:
一、Python语言自身
-
Python官方文档更喜欢采用单引号。(Python 3.6: 80% vs 20%)
-
Python标准库更喜欢采用单引号。(Python 3.6:74% vs 26%)
-
repr() 采用单引号。
二、现实世界
-
很多热门开源Python项目用单引号。(无数据支持)
-
有些公司要求使用单引号。(无数据支持)
-
PEP 规范里的例子更多地使用单引号。(无数据支持)
-
Guido(Python之父)更倾向于使用单引号。(无数据支持)
-
有些程序员用双引号表示供人类阅读的字符串,用单引号表示供机器阅读的字符串。
三、工具
- 在Sublime Text里,使用双引号会导致一些高亮颜色失效。
四、易读性和易写性
-
使用某些字体时,单引号空字符串比双引号的空字符串更难辨认。
-
双引号造成更大的视觉干扰。
-
采用双引号就不必转义ASCII的单引号。
-
采用单引号就不必转义双引号。
-
大部分键盘布局都更容易打出单引号。(美国、中国、英国的键盘都更容易打出单引号,其他的键盘布局至少单引号和双引号需要同样次数的按键,不存在双引号更容易打的情况)
五、其他语言
-
C语言使用双引号。
-
其他流行编程语言都用双引号。(如C#, Java, ...)
-
英语散文的引用使用双引号。
为什么说这位zestyping是重量级人物?
因为他刚整理完各方观点,ambv就来say hi。
原来zestyping之前也为Python贡献过代码,ambv的black实际上还使用了zestyping贡献的lib2to3,所以ambv感谢了zestyping的贡献。
感谢归感谢,ambv还是逐条指出论据的瑕疵
Python官方文档更"喜欢"地采用单引号。Python标准库更多"喜欢"采用单引号。
ambv认为这两个论据不对。单引号是使用得更多,但官方并没有推荐任何一种引号。ambv很肯定大部分作者都不关心使用哪种引号。
Guido更倾向于使用单引号。
ambv说他跟Guido谈过心,这条也不对。Guido说他喜欢把双引号用在给人读的文本,把单引号用在数据上。
在Sublime Text里,使用双引号会导致一些高亮颜色失效。
ambv说"This make me sad"。这明明是一个bug,应该去修复它,怎么会成为支持单引号的论据?
双引号造成更大的视觉干扰。
ambv怀疑这是不是由于一些字体设计得过于糟糕。"什么是衡量视觉干扰的单位?两种引号之间的视觉干扰数值差异有多少?就算我们能回答上述无聊的问题,我也肯定差异很少,就像M比N的干扰更大、逗号比句号的干扰更大一样无聊。"ambv连珠炮般地抨击。
zestyping 见到ambv的抗议后,改成:
-
Python官方文档更"多"地采用单引号。
-
Python标准库更多"多"地采用单引号。
-
Guido更"多"地使用单引号。
最终妥协
打动ambv的似乎是一个叫kadrach的用户做的统计。他统计了下载量最多的前100名python库里单引号占比的分布图,如下图所示:
ambv很感兴趣,当然他也马上指出这个统计不完善,因为这里包含了备注和其他字符串里的引号。他要求用AST(不知什么意思,大概是语法树?),统计前1000名的库,并且重复的文件只统计一次。
ambv和kadrach就这个统计的实现方法讨论了很久,在这过程中ambv的立场似乎逐步软化(虽然我没看到有什么统计成果)。
这时一个叫kbd的用户做结案陈词:纵观整个帖子,最重要的论据是很多人(包括Python之父)都使用不同的引号来表示不同的意思,双引号表示"人类可读的文本",单引号表示"数据"。kbd说检查了自己的代码,发现自己下意识地也遵循了这种规范,所以这种潜意识可能是普遍现象。
ambv马上表示同意,他认为这也是最有说服力的论据。这一天是2018年5月30日。
在几个人附议之后,ambv在5月31日发布了18.6b0版本,终于提供了 --skip-string-normalization 选项。
这个issue是4月9日提出的,4月12日被关闭,5月27日重开,5月31日解决。
ambv看上去固执,实际上还是很关注大家的意见,并且很讲道理的。
I hope this resolves to your satisfaction what's been the most controversial issue in Black's history.