作为 Stack Overflow 里 Python tag 下有 6k+ reputation 的开发者,我觉得我可以从两个角度来谈谈我的看法,Python 这门从 1991 年诞生的语言有很多独特的地方,它的语法极其简单,上手十分容易,很多方法都是简洁的单词,比如 split,index,append,extend, 一门语言抽象的最好的结果就是写代码就完全像是说话一样,编程语言是一个沟通的桥梁,你用人类的语言(英文)去和程序沟通,程序将你的代码翻译成机器所能理解的可执行的字节码或其它目标文件,而 Python 恰好就是这样一个提供了丰富内置函数和大量语法糖的语言。
一. 如何学习 Python 语言
1.大道至简 -> 去看书!我很倾向于读书学习技术,很多经典书籍的结构是千锤百炼的,它帮助你由点及面,触类旁通,摄取知识的速度和广度远远大于其它类的教学(下面的书基本上都有中文版):
- Learning Python, 5th Edition (中文应该是Python 学习手册 ,这本书就像白居易写诗一样,力求通俗易懂)
- Fluent Python (豆瓣) (比较进阶的书籍)
- High Performance Python
- Effective Python
上面几本书是语言入门进阶的经典书籍(具体领域有针对的书籍,不想一一列举),不仅会有基础语法,Built-in functions 的介绍和使用技巧, Python2 和 Python3 的简单区别介绍,还有一些优化技巧和最佳实践,历经这么多年的推敲,这些书的结构和例子已经十分简单清晰。
『读万卷书,行万里路』,在我看来是在说,实践得真知,编程对我来讲和作曲,写文章类似,是一门创造的艺术,去大胆的写,实践会帮你加深记忆,让你对语言运用自如。
除了看书,还要去看别人写的项目,这里指代的不是教你写爬虫,写2048游戏的,网上类似的东西抄来抄去,而且质量参差不齐,看著名的开源项目能帮你如何正确理清逻辑关系,处理代码框架,以及哪些特性适用于什么场景,我推荐的:
- pallets/werkzeug (WSGI)
- requests/requests (Python 中数一数二的项目)
- tornadoweb/tornado (知名 web server,以快著称)
还有一个地方就是 Python 官方的文档,Python documentation ,里面有很多奇珍异宝, 高阶函数,比如鲜为人知的 itertools – Functions creating iterators for efficient looping ,还有书中较少用到的内置函数。
除了看书之外,有一个东西是一定要看并且要熟稔于心的,那就是 PEP 8 — Style Guide for Python Code ,或者这个 Python风格规范 – Google 开源项目风格指南 ,Python 的写法很多变,所以好的 Python 编码风格不仅会让你的代码看起来舒服很多,也能帮你减少不少编码错误。
如果你对 PL 感兴趣,没准你也可以去看看 yinwang0/pysonar2 ,王垠写的 Python 的类型推断器。
2. Pythonic
当一些 Python 开发者写了一段时间之后,往往会想更进一步,也许就会在社区内注意到一个词就是 Pythonic,就是如何写的更 Python 化,其实具体做法就是大量使用其语法特性,减少冗余代码,比如 list comprehension 就会帮助你减少创建一个中间变量,不断腾出内存空间,而是先找出所有元素再去创建 list。
举个小例子:
如何把嵌套的 list :a = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] 拍平成 [1, 2, 3, 4, 5, 6, 7, 8, 9]?
Normal way
flat_list = [item for sublist in l for item in sublist]
Pythonic
sum(l, [])
上面的方法虽然够 cool,但是效率并不好,所以有下面一个方式
functools.reduce(operator.iconcat, l, [])
可以看看这个问题下的讨论 How to make a flat list out of list of lists?
实际使用中,开发者会慢慢在以下优先级中取舍,易读易维护 >= 性能 > Pythonic,所以很多时候 Pythonic 并不是唯一衡量 Python 代码质量的标准,切记。
3. 大型项目如何避免遇到动态语言带来的坑?
Python 到底能不能写大型项目?这取决于开发者,YouTube,Instagram,Quora,Uber,Netflix,知乎等等项目很多都是 Python 搭建的,在代码规范做得足够好的情况下,它不仅能保证开发迭代的高效率,也能保证工程的稳定。问题是很多开发者并没有严格遵守 Python 代码风格规范和基本的编程原理,所以写出来的工程代码很不可控。动态语言的特性可以尽管使用,但是要遵循其使用原则和场景,最好把 Unit test 补充完整,给项目保险。
我的建议是除了极其严格的代码风格规范之外,把 Python 当成编译语言来写,少用 if variable 而是 if variable is None 或者 if variable == 0 或 if len(user_list) == 0,每个函数下面都将参数与返回的类别用注释定义清楚。让 IDE 为你自动解析代码并 warning,pycharm有着强大的语法解析功能,时刻注意看它的提醒与建议,比如
def foo(arg={}):
pass
很多人觉得没什么,可以跑起来,然而注意 pycharm 是会警告的,这是很有可能带来不易发觉的错误的,类似的地方,把 IDE 带来的 warning 慎重对待,除了编码风格之外,隐藏的类型不匹配,作用域,unbound method 等等问题都是对你代码的健壮性有很大提升和帮助的,除此,大型项目一定要注意代码结构的设计,层级之间逻辑分明,不要上下层相互调用,不然循环引用也是很容易出现的。
4. Hidden features
关于 Python 有哪些隐藏的,不太为人所知的语法糖或者使用技巧,可以看看 Stack Overflow 上这个回答,其它语言也有类似的,但是 Python 的这个真的可以写成又一本书了,其中涉及到 unpacking,In-place value swapping,context manager,nested list/generator comprehensions 等等 :
https://stackoverflow.com/questions/101268/hidden-features-of-python
5. 值得去看看的 Python 在 Stack Overflow 的提问
- Immutable vs Mutable types (mutable 和 immutable 是 Python 中十分重要的概念)
- How can you profile a script?
- How to clone or copy a list? (很多语言的复制默认是浅拷贝,Python 中的拷贝原理需要仔细看看)
- What are metaclasses in Python? (metaclass 是比较高阶的用法了)
- What is the difference between @staticmethod and @classmethod? (OOP 中常用的点,经常用来考核面试者)
- Are static class variables possible?
- Usage of __slots__? (slots 可以帮你节省大量内存,但是也是有场景的)
- What’s the difference between lists and tuples? (掌握语言的基本就是要知道不同数据类型的使用场景以及优势,比如 tuple 实现了 hashable 可以作为 dict 的 key,list 就不行)
- What does the “yield” keyword do? (试着比对一下 generator 和 iterator 的不同)
还有很多优秀的提问和回答,Stack Overflow 上可以翻一翻比较靠前的提问。
补充
6.有关 Python 性能
不少项目中使用一种语言,在技术选型的时候会考虑多个方面,比如开发人员是否熟悉,一些创业公司开始确立的 tech stack 是看创始团队熟悉什么语言,以及生态是否成熟,是否符合应用场景,Python 很多时候是用来快速迭代产品原型或者作为胶水语言,那么是否就真的性能很不堪呢?
Python 是个动态的强类型的解释型语言,它有多个版本的实现, 比如 CPython (官方用 C 的实现,目前应用最多,但是受制于 GIL,且不支持 JIT,于是执行速度略差),IronPython(.NET),Jython(Java 实现, 性能比较好,但是启动慢),PyPy(Python 自身实现,集成了 JIT,比 CPython 快三倍,但是不支持官方的 API,扩展性差,缺少第三方库的支持),很多时候性能还真不是开发者使用 Python 的主要原因,更多方便的内置函数与库支持才是,所以很多开发者首选 CPython 而不是其它性能更优的版本。
相关 benchmark 和讨论可以看这里:
Which is the fastest version of Python?
Python 在性能优化和提高工程质量的路上需要有很多地方要做,比如最初的架构设计,严格的 Code Review,经验人士付出不少精力才能提高至不少静态语言才能达到的性能和工程质量,这也是为什么一些开发者宁愿去试试简单的静态语言(Golang)也不愿在 Python 上多耗费精力的原因,静态语言起码能用编译时错误暴露代码的风险,而动态语言就不容易发现了,而有些静态语言经常会在运行时崩溃,于是 Rust 就干脆把这些校验都放到了编译期间去尽量检查(没记错的话 C++ 也有这个趋势)。
在编程语言的运用上,当你了解了它的优劣,说明你慢慢开始精通,用得也会得心应手。
二.写 Python 拿来做什么
这是一个我十分想要说的点(算是一点职业建议),很多人写文章都在说,写 Python 做机器学习啊,用 TensorFlow 啊,201x 年什么最火?人工智能啊!说出来高端,学起来不难,就是调用几个 module 的事情,我觉得上面有一个回答说的很好,非常好:
技术这个东西,要能钻进去也要能跳出来。
就像我上面所讲的,编程语言是用来沟通的,至于你想要表达什么含义,做什么东西,都是可以使用不同的语言甚至方言去表述的,记得有一位网友也说过一句话,很有道理:
如果你用一门语言能做到某某事情,换了一个语言就做不了了,那说明那门语言很厉害,而不是你。
Python 可以做的事情很多,云计算(OpenStack),支付系统(PayPal),Machine Learning(scikit-learn),NLP(NLTK),游戏的开发,机器学习,甚至现在嵌入式领域 Python 也在慢慢地发展起来。具体做什么东西,你要理解的是其原理,而不是语言本身。
举例子来说,你学服务器端开发,你对各种关系型,内存型,文档型数据库的使用场景都不清楚,对关系型数据库的底层存储引擎适用于什么场景,如何处理并发,处理数据的一致性都不知道,这是不合格的,你做机器学习,对于决策树,贝叶斯,K-means,FP-Growth 内涵都不清楚,这也是不及格的,这也是上面我不列举 利用Python进行数据分析 (豆瓣) 这类书的原因,这类书大部分是介绍某些库的接口和使用,很少涉及底层原理,而作为专业领域的开发者一定不能局限于语言。
这就是要 钻进去也要跳出来 。