我如何使用Python进行大规模开发?
我想了解一下在Python中进行大规模开发的情况,特别是如何维护一个庞大的代码库。
当你对一个方法的签名(也就是方法的名字和参数)做了不兼容的修改时,你是怎么找到所有调用这个方法的地方的?在C++或Java中,编译器会帮你找到这些地方,但在Python中你该怎么做呢?
当你在代码的深处做修改时,怎么知道一个实例(对象)提供了哪些操作?因为你没有静态类型可以查找。
你是如何处理或防止输入错误(比如拼写错误)的?
单元测试(UnitTest)是否可以用来代替静态类型检查?
可以想象,我几乎只用过静态类型的语言(C++/Java),但我想尝试在Python中做一些大项目。不过很久以前,我在使用clipper(dBase)语言时有过很糟糕的经历,那也是一种动态类型的语言。
8 个回答
我之前有修改过一个叫“Frets On Fire”的开源游戏,它是个类似“吉他英雄”的游戏,用的是Python语言。
我觉得Python不太适合做特别大的项目。
在开发过程中,我花了很多时间去调试一些类型不匹配的问题,而这些问题在静态类型的语言中,编译时就能轻松发现。因为Python是在运行时才确定变量类型,所以理解已有代码就变得困难了,因为你根本不知道你正在看哪个参数的类型是什么。
另外,在Python中,使用字符串形式的函数名来调用函数(通过__getattr__
这个内置函数)是比较常见的,这让我们想要追踪某个函数的调用关系变得有点麻烦(虽然在一些静态类型的语言中也可以用名字调用函数)。
我认为Python在小型软件、快速原型开发和把现有程序组合在一起时表现得很好,但我不会用它来做大型软件项目,因为在这些项目中,维护性才是个大问题,而我觉得Python在这方面相对较弱。
别把螺丝刀当锤子用
Python 不是一种静态类型的语言,所以别试图用那种方式来使用它。
每种工具都有它的用途。对于 Python 来说,这意味着:
鸭子类型:没有类型检查。只关注行为。因此,你的代码设计要考虑到这一点。好的设计意味着通用的函数签名,组件之间没有依赖关系,抽象层次高……所以如果你改动了某个地方,其他代码就不需要跟着改。Python 也不会抱怨,这正是它的设计初衷。类型问题不是问题。
庞大的标准库。如果你使用的是标准功能,而不是自己写的代码,你就不需要在程序中修改所有的调用。Python 自带很多功能,我每天都在发现新东西。刚开始的时候,我根本不知道可以用多少模块,只是像大家一样试图重写已有的东西。没关系,刚开始不可能什么都对。
你不能用同样的方式来写 Java、C++、Python、PHP、Erlang 等等。每种语言都有它存在的理由,它们并不是做同样的事情。
单元测试不能替代其他东西
无论使用什么语言,都必须进行单元测试。最著名的单元测试库(JUnit)来自 Java 世界!
这和类型无关。你检查的是行为。这样可以避免回归问题,确保客户知道你在按计划进行。
Python 适合大规模项目
语言、库和框架本身并不能扩展。架构才是关键。
如果你设计了一个稳固的架构,并且能够快速发展,那么它就能扩展。单元测试和自动代码检查都有帮助,但它们只是安全网,而且是小型的。
Python 特别适合大型项目,因为它强制一些好的实践,并且内置了很多常用的设计模式。但再次强调,别用它去做它不擅长的事情。例如:Python 不是用来处理 CPU 密集型任务的技术。
在一个大型项目中,你很可能会使用几种不同的技术。比如一个 SGBD(法语的 数据库管理系统)和一个模板语言,或者其他的。Python 也不例外。
你可能会想用 C/C++ 来处理需要快速的代码部分,或者用 Java 来适应 Tomcat 环境。无所谓,Python 可以很好地与这些配合。
总结一下
我的回答可能听起来有点直接,但别误会:这是个很好的问题。
很多人带着旧习惯来学习 Python。我曾经试图用 Python 的方式去写 Java,结果搞得一团糟。你可以这样做,但永远无法发挥出它的最佳效果。
如果你玩过或想玩 Python,那太好了!这是个很棒的工具。但说到底,它只是一个工具而已。
既然没人提到pychecker、pylint和类似的工具,我就来讲讲:pychecker和pylint是一些可以帮助你发现错误假设的工具,比如函数的写法、对象的属性等等。虽然它们找不到编译器在静态类型语言中能发现的所有问题,但它们也能发现一些编译器找不到的问题。
Python(以及任何动态类型的语言)在你可能犯的错误类型和如何检测、修复这些错误方面,跟静态类型语言是完全不同的。它有明显的优缺点,但很多人(包括我)会认为,在Python的情况下,写代码的简单性(以及让代码结构合理的简单性)和在不破坏API兼容性的情况下修改代码(比如添加新的可选参数,提供不同的对象但它们有相同的方法和属性)使得它非常适合大型代码库。