大约两年半前,我萌生了创建一个新的系列文章的想法,即“WhyPython”,试图就Python的语法和特性提出“为什么”的问题,以加深理解我对它的理解。了解和探索使用技巧、发展演变和设计理念等主题。我一直是一个好奇心很强的人,问题意识很强,善于辨别相似事物的差异,并从差异中发现事物的独特意义。所以,在比较Python和其他编程语言的时候,加上阅读和翻译一些PEP积累了一些素材,有了很多小发现。在确认国内外技术社区缺乏这方面的文章后,我更加相信这件事的独特价值。我当时有一个天真的想法,认为我可以用“十万个为什么”的方式源源不断地写文章……2020年上半年,我非常有创意,写了大约20篇“WhyPython”的文章系列文章!然而,2021年,只有2个!2022年只有2篇!!……所有的时间都去哪儿了?为什么我只是偷了一点懒惰,它就消失了?本来打算有很多题材想写的,可是怎么就拖延了,忘记怎么写了。。。最近眼看年关了,越想越不甘心我是,所以我花了几天时间整理了一下。下载《WhyPython》系列文章,优化Github介绍内容,准备认真pick这个系列!我把之前问卷遗留的问题和其他我打算写的主题放在Issues轨道上。欢迎大家提问/建议/指导写作/监督更新……以下是本期系列文章的介绍,请喜欢本系列的同学给个star鼓励一下!(内容会持续更新/增加,请参考Github主页。)如果您是手机微信阅读,由于链接跳转比较麻烦,建议您通读本合集中的链接。文章列表关于Python设计和历史的常见问题Python官方提供了大约30个常见问题的常见问题解答,从中你可以快速获得“权威”的解释为什么Python使用len()函数而不是x.len()样式?-and-not-x.len().md)介绍了《流畅的Python》和Guido的解释。我个人认为这体现了Python对世界本质的洞察。文章顺便回答了:Python的索引为什么从0开始计数?为什么Python要用缩进来划分代码块?这是一个永远被提出来的经典问题。我总结了8个原因,上面8个原因很多人不买账,所以我加了个回复:Python的缩进绝不是反人类的设计!Guido在接受采访时表示:严格要求代码缩进确实有点夸张。改用花括号也不是不可能。Python的缩进起源于ABC,ABC的缩进起源于60、70年代的编程。分号作为语句终止符?分号一般有分隔符和终止符两种作用,但是Python只把分号当作分隔符,并没有把它当作终止符。相反,它使用换行符作为终止符。这篇文章总结了Python没有main函数的5个原因?为什么我不推荐写主函数?main函数作为一些编程语言的执行入口是必须的。但是Python这种脚本语言,有自己更灵活的执行方式。在我的编程习惯中,我不喜欢那些不假思索的if__name__=='__main__'的写法,我的编程建议在WhydoesPythonrecommendsnake-likenomenclature?一文中给出了我的编程建议?编程语言中有几种变量命名风格,最流行的两种是驼峰命名法和蛇命名法。本文从编程语言的历史发展和语言内部的使用习惯的角度解释了为什么Python更喜欢蛇形命名法。为什么Python不支持i++自增语法,也不提供++运算符?有C/C++/Java等语言编程经验的开发者会疑惑为什么Python中没有i++这样的语法。这个问题反映了Python中的数字对象与其他语言中的数字有根本的不同;此外,PythonPython的可迭代对象特性也深刻地影响了该语言的许多设计方面。为什么Python只用一条语句“a,b=b,a”就可以直接交换两个变量?很多人认为“a,b=b,a”(交换变量操作)和“a,b=1,2”(多元赋值)一样,都是基于元组拆包的特点,但是CPython的实现是不像这样CPython使用特殊的优化指令(即ROT_TWO、ROT_THREE和ROT_FOUR)来快速交换堆栈顶部的元素。当同时交换的元素个数大于4时,解释器会跟"a,b=1,2"(多元赋值)一样,Python为什么要用#号作为注释来实现变量赋值基于拆包?注释是编程语言中最基本的元素之一。Python属于“#注释阵营”,或许是因为它沿袭了Shell等脚本语言。传统Python中没有“块注释”。Guido曾经建议使用multipleLinestrings(多行字符串)来实现块注释的效果,但是这个方案在语义上有点奇怪。为什么Python有pass语句?pass是Python特有的一种空操作。其他语言没有这样的设计。pass可以作为空格占位符,辅助程序员快速编程。然而,这个小用途并不重要,因为Python不使用大括号。和其他划分代码块的手段,所以当定义一个空函数时,pass就成了补充语法逻辑的解决方案为什么Python会有一个奇怪的“...”对象?...是Python3在PEP-3100中引入的内置常量,它表示与Ellipsis相同的对象。官方说他们是单例,但这与事实相悖。文档是错误的还是这是一个错误?...有什么用,能解决什么问题?文章介绍了4种用途:扩展切片语法、表达“未完成代码”语义、TypeHint用法和表达无限循环。为什么Python可以支持任意真值判断?这也是Python的一个显着特点。它将其他语言中仅限于布尔类型的操作(if或while或布尔操作and、or、not)扩展到任意对象,带来了极大的灵活性。判断的结果取决于\_\_bool\_\_()和\_\_len\_\_()这两个魔术方法的返回值Python甚至可以对number对象(number代表0为False,其他数字为True)为什么Python函数默认返回None?Python隐式地给没有return的函数加上return操作,即默认返回一个None值,这是解释器强行注入的逻辑。这意味着:Python中没有不返回值的函数。为什么Python强制所有函数都有返回值?为什么它不支持不返回任何内容的空函数?为什么Python没有void关键字?void通常指的是一种类型(type),但它没有具体的值(value)。文章介绍了其他语言需要使用void关键字实现的两个功能。Python舍弃了void,即“没有值的类型”,统一使用None,即“只有一个值的类型”。配合上一篇“所有函数必须有返回值”的设计,达到简单易用的效果。为什么Python是强类型语言,而不是弱类型语言?动态类型和静态类型以及强类型和弱类型是两个不同维度的概念,不能混为一谈,在编程语言发展初期,强类型和弱类型的概念还没有提出来的时候,一些大佬用动态类型和静态类型来描述特性通用语言。这是历史原因。现在主流观点是用“隐式类型转换”来划分强类型和弱类型,Python无疑是一门强类型语言。针对几个容易混淆的问题,本文详细解释了为什么会有Python中没有“隐式类型转换”,为什么Python之父不喜欢lambda匿名函数?lambda语法是从lisp语言中借来的,却被父亲否决了蟒蛇。然而,它在他的屠刀下幸免于难。这个故事充满戏剧性。Python的lambda只支持单行表达式,功能不完善。有人曾经提议增强lambda语法。Python之父认为这不是一个好的设计,因此拒绝了Guido提出的一次性去掉reduce()、map()、filter()和lambda的提议,但最后妥协了为什么Python不支持switch陈述?大部分语言都提供了switch语句或者非常类似的东西,但是在Python之父的统治下Python并没有提供switch语句。[Python困境:[]或list()哪个更快?为什么要快?快多少?](https://github.com/chinesehua...[]-faster-than-list().md)创建列表的两种方式[]和list(),哪个更快,为什么更快?快速地?文章通过对字节码和执行过程的分析,解释了两者在执行速度上的差异。为什么说Python内置函数不是万能的呢?内置函数的名称不是关键字,内置作用域在名称查找中处于最低优先级,因此在调用时,某些内置函数/类型的执行速度明显慢于其对应的字面量representation为什么继承Python内置Type会出错?!从《流畅的Python》中的例子,引出了Python对内置类型的子类化这个不合理的话题。分析了魔术方法的底层实现逻辑和调用关系,解释了内置类型存在的问题,介绍了内置类型子类化的最佳实践。为什么Python的f-string可以连接字符串和数字?Python是一种强类型语言。没有强制类型转换,字符串不能与数字连接。介绍了PEP-498实现f-string的原理。为什么Python的slice索引没有越界?切片是许多编程语言的一个特性。Python的切片不仅功能齐全,而且使用起来更加灵活。索引交叉是一个常见问题。Python切片使用多种规则来屏蔽可能的错误。文章介绍了Python的解决方案,但也留下了一个疑问:为什么Python的slice语法允许索引越界,为什么没有设计成抛出索引错误?为什么range()不生成迭代器?-generate-an-iterator.md)有很多生成迭代器的内置方法,但是似乎只有range()生成迭代对象,这个range()非常独特。我的猜测在文章中给出。我还注意到range是一个不可变的序列。但是,与不可变字符串序列相比,它也有独特的性能。Python为什么要保留显式自我?这也是一个普遍的问题。这里给出官方文档的解释,附上Guido的博客全文。为什么Python不设计do-while循环结构?在C/C++、C#、PHP、Java、JavaScript等语言中,do-while是一种基本结构。为什么Python不遵循他们的传统?有什么特别的注意事项吗?文章列举了do-while语法在其他语言中的主要使用场景,解释了为什么Python不能使用这种结构,介绍了PEP-315引入do-while结构的尝试,以及Guido反对为什么Python3改print为function?Python3和Python2最显着的区别之一是print语句变成了print()函数PEP-3105Makeprintafunction是这个问题的最佳答案WhyitisthemostmagicmagicmethodinPython?\_\_missing\_\_()是一种只存在于内置类型的子类上的神奇方法,似乎是唯一的特例\_\_missing\_\_()是如此特殊以至于Python解释器打开后门实现了最罕见的“魔术方法调用”逻辑。为什么Python使用“elif”而不是“elseif”?elif的写法比“elseif”更简洁,这种写法在Python中也不是首创。吉多发推文解释了这篇文章的出处。两年半前写第一个“PythonWhy”系列时,我无法想象自己写这篇文章宣告2023年新的开始。对于一个总结,更难以想象在接下来的时间写一个新的总结两年半,或五年半或更长时间。谁知道!但是,只要不忘初心,珍惜当下的决心,树立奋发向上的毅力,我就能做到!最后,别急着刷走,记得点关注,点个星哈,喵喵~~
