在开发人员的职业生涯中,有一个特定的阶段,开发人员从为项目做出贡献到精通技能。有的人来得早,有的人晚,有的人永远达不到这个阶段。然而,大多数职业生涯较长的开发人员都会经历这个阶段。我称之为自我建构点。如果你已经到了那个阶段,你面临的第一个问题是:它是如何运作的?用户体验如何?结构是什么?数据如何流动?还有很多这样的问题。我不会在这里为你回答这些问题。无论你从哪个项目入手,都需要根据项目进行高度定制化,并且每个人至少要有一篇独立的文章来回答。但是,我想回答其中一个问题:哪种语言最适合这个项目?您可能认为这取决于项目类型,确实如此,但每种编程语言都有一些缺陷。事实上,Python也有很多缺点,尤其是当你试图用它来构建一个大型程序时。1.变量声明不存在,这是个问题Python之禅表明显式优于隐式。但是当谈到变量声明时,Python中的隐式比显式更常见。(注:TheZenofPython指的是TimPeters编写的python编程指南。)让我们看一下下面的一小段C代码:charnotpython[50]="Thisisn'tPython.";在此之前,让我们深入探讨以下问题。“char”是一个类型标识符,表示其后的所有内容都与字符串相关。“notpython”是我给这个字符串起的名字。[50]表示C会为此预留50个字符的内存空间。不过,在这种情况下,我可以使用19个字符——每个字符一个,最后加上一个空字符\0,并以分号整齐地结束。这种显式声明在C语言中是强制性的。如果省略它,编译器将罢工。这种方法起初可能看起来愚蠢而乏味,但它会带来巨大的回报。两周或两年后,阅读C代码,你突然发现一个你不知道的变量,所以只需要查找声明即可。如果你给它起一个有意义的名字,那将给你一个很好的提示,告诉你它是什么,它在做什么,以及它的用处。与Python不同,您几乎可以随时创建变量。但是如果你不给它一个有意义的名字,或者至少留下一个关于它的注释,它将来可能会一团糟。在Python中,除了深入研究代码之外,很难理解变量在做什么。即使您在变量中输入错误,也可能会破坏整个代码——Python没有像C那样的保护声明。如果您正在处理较小的项目,或者不是很复杂的项目,比如几千行代码,这很好,但如果它是一个更大的项目……那就太糟糕了。您可以在Python中进行显式变量声明,但只有一些非常勤奋的程序员会这样做。当编译器没问题时,许多程序员往往会忘记这些额外的代码行。写Python很快,对于小而简单的项目,阅读Python也很快。但是在阅读和维护大型Python项目时,您最好成为查找描述性变量名称和注释所有代码的世界英雄,否则您就完蛋了。2.模块,你属于哪里?如果你认为事情不会变得更糟,那你就错了。变量在代码中“存在”在哪里的问题不仅来自隐式声明,还来自其他模块,通常以类似my_module.my_variable()的形式出现。如果您对这样的变量感到困惑,那么当您检查它出现在主文件中的其他地方时,您仍然会感到困惑。您还必须检查您的代码是否包含以下两行之一:importmy_modulefromanother_moduleimportmy_module第二行告诉编译器您需要包含更多内容的模块中的某个函数或变量。这很烦人,因为PyPI上的模块比你在PyPI上找到的要多,并且在你的计算机上导入任何其他Python文件。因此,快速搜索您的函数和变量并不完全有益,甚至可能更糟。模块可以依赖于其他模块。因此,如果你不走运,你导入了模块A、B和C,但这些模块依赖于模块E、F、G和H,而这些模块又依赖于模块I、J和K。突然间,而不是3模块,你需要管理10个模块。更糟糕的是,有时它并不是这么简单的结构。比如模块B和C还依赖模块M和N,J也依赖M,C和H又依赖Q……后面不用说了,你懂的。这是一个迷宫,是一个真正的Python人创造的依赖地狱。循环依赖是迷宫中最丑陋的野兽。如果模块A依赖于模块B,但模块B也使用模块A的一部分......在小项目中这不是问题,但在大项目中......欢迎来到丛林。3.很多依赖冲突。我抱怨的不仅仅是模块本身,还有它们的版本。原则上,Python拥有活跃的用户群,许多模块定期更新,这是非常好的。只有一个问题:并非所有版本的模块都始终与其他模块兼容。假设您使用模块A和B,并且都依赖于模块C。但是A需要3.2或更高版本的C,B需要2.9或更早版本的C。但是您不关心模块C,您只需要A和B.世界上没有任何工具可以帮你解决这个冲突。运气好的话,您会找到与您有相同问题的人编写的补丁。如果你不是那么幸运,你将不得不编写一个补丁。或者你使用另一个包。或者,您可以重写其中一个包(A或B)并找到需要C的解决方法。无论如何,您都需要额外的时间来解决问题。这就像在丛林中,您需要耐心和一些导航工具才能找到出路。除了依赖冲突,还有一些不错的工具。像“pip”一样,它使安装包变得容易。使用简单的“requirements.txt”,您可以指定要使用的包和版本等。虚拟环境将所有包保存在一个地方,并与主Python分开安装。对于更大、更复杂的项目,还有“conda”、YAML文件等。但是你需要学习如何使用每种工具,以确保在最短的时间内解决问题。4.不同的机器,不同的Python即使你在机器上解决了所有的依赖,你的Python运行的非常流畅,也不能保证它在其他机器上仍然运行得如此流畅。“pip”、“requirements.txt”和虚拟环境等工具可以帮助您驾驭轻度依赖地狱,但仅限于本地。在每台新机器上,您都需要检查并重新安装各种版本和要求。唯一简单的解决方案是Jupyter笔记本。在Jupyternotebooks中,你可以使用任何你喜欢的版本来编写。在Jupyter中,一切都在在线服务器上运行,您可以将这些文件发送给任何人,他们也可以使用它们。然而,这也有一个明显的缺点:Jupyter笔记本只有图形界面。但是使用图形界面,处理包含许多相互关联的文件的大型项目是相当困难的。也许这就是为什么我很难在Jupyter笔记本中看到大型项目。只要有其他语言的虚拟机,问题就迎刃而解了。5.pip之外的世界假设你已经成功地通过使用Jython或PyPy或其他一些解决方案将你的项目移植到不同的机器上(这些比虚拟机处理起来有点笨拙,但至少它可以工作),然后Down要集成大型项目,您可以集成C包、Fortran包等。这样做有很多好处:C包在Python中可能不存在,而且通常速度更快。由于遗留原因,科学包往往只存在于Fortran中。但实际上,你必须在这个过程中使用'gcc','gfortran'等编译器-这很麻烦,因为在Python代码中集成C模块的文档超过4500字,集成Fortran的文档不是短要么。因此,从一开始就用C构建整个项目可能会更好:速度较慢,但??您可以避免使用多个编译器和接口。C很旧,几乎所有东西都有包,甚至是用户友好的机器学习包。6.使用全局解释器锁来锁定性能自Python诞生之日起就存在的全局解释器锁(GIL)使得最终用户的存储管理变得非常容易。至少在较小的项目上,开发人员在使用Python时根本不需要考虑计算机内存。相比之下,在C中,每个变量都保留了一点内存!基本上,GIL计算在代码的每个部分中引用变量的次数。如果不再需要该变量,则释放它占用的内存空间。所以在小型项目中,GIL有助于提高性能,因为清除了不必要的内存空间。但是在大项目中有一个问题:GIL不喜欢多线程。这是一种大大提高执行器性能的方法,其中多个指令线程在相同的进程资源上独立运行。机器学习模型非常适合以这种方式进行训练。只有一个小问题:GIL一次只能在一个线程上工作。因此,如果变量A在线程1上执行,而线程2对变量A执行完毕,则其内存可能会被删除,具体取决于当时GIL所在的位置。可以想象,这会导致非常奇怪的错误。当然,有解决方法,但没有一个是完美的,因为它通常不如使用GIL的语言中的多线程快。7.并发和并行仍然很笨拙和令人困惑我们发现并发的一个缺点是当你在多线程时,全局解释器锁会减慢速度,或者导致奇怪的错误。Python的协程也存在同样的缺点。线程和协程有一些细微的区别,即协程一次执行一个任务,而线程可以同时执行多个任务。相同的是它们都是并发的实现。当您有大量任务需要等待时,协程很有用,例如,您正在从网站读取数据并等待服务器响应。协程不会让计算机闲置,而是给它分配另一个任务。另一方面,当你有多个耗时任务时,线程的优势就体现出来了,它不会占用太多的CPU,也不需要太多的等待。如果您有CPU密集型任务并希望充分利用硬件,那么并行性值得考虑。Multiprocessing也是一个不错的选择,它会告诉计算机使用多个内核,节省时间。然而,线程、协程、多处理这三种技术都面临着一个相似的问题,即用Python实现起来并不难,但代码看起来笨拙难读,尤其是初学者。Clojure、Go和Haskell等语言在并行性和并发性方面要好得多。如果你不是在处理缓慢或密集的任务,你就不需要考虑它。但如果是,您可能需要重新考虑您的选择。8.用什么代替PythonPython有其自身不可忽视的优点,但也确实有缺点。如果你想要声明良好的变量和开发良好的包来避免依赖地狱,C是很好的选择。如果您想要可移植到任何机器的东西,那么Java、Clojure或Scala都是不错的选择。它们在虚拟机上运行,??所以你不会遇到像Python一样的麻烦。如果你想运行大型、缓慢的任务,你可能想尝试Go或Haskell。一开始它们比Python更难学,但是你投入的时间会得到回报。您还可以组合不同的语言,例如Python非常适合快速编写脚本、草图,甚至是中型项目。我认识的许多开发人员用Python编写初稿和测试运行,然后用C、Go或Clojure重写重要部分。这允许代码执行得更快,同时仍然利用Python必须提供的优势。在大型项目中使用Python并非不可能,只是在许多情况下它不是唯一的:您可以使用Python将C、Go或Clojure的片段拼凑在一起。如果您已经达到了构建自己的目标,请记住没有一种语言是完美的。尽管有缺点,Python仍然很棒且方便,您可以通过集成其他语言的代码来避免Python的这些缺点。觉得Python太难学?给大家分享一份大佬整理的学习资料。无论是零基础入门,还是想提升自己的Python专业技能,都可以免费获取。关注gzh【Python编程学习圈】,回复【学习资料】,让你的学习更轻松高效!
