会用一门语言写代码并不能说是掌握了这门语言,尤其是入门容易的语言,掌握起来更困难。你说你会用汇编写程序,我可以承认你掌握了汇编语言,而你说会用Python写程序,十有八九真的只是会写而已。
有基础的哥们,Python能在3分钟内入门,其他解释性语言也是如此,不用花太多时间,就能说我会了,只要能让我查google。我从大一(2011)开始接触Python,几乎每个月都在学新的内容。当然,我新学的内容不是Pythonic。
Python基础库
我很久以前买了一本很厚的《Python标准库》,结果才看了不到100页。最近,我才真正认识到标准库的作用。此处,我不会考虑Python 2,我只会Python 3。
unicodedata
unicodedata
对我这样的多语言工作者还是比较有用的,目前这个库只提供了各个unicode字符所属的类别,如’我’是符号类别(‘Lo’),’1’是数字类别(‘Nd’),这样我就不用翻wikipedia了。不过,这个库也没有完全满足我的需求,经常需要查阅unicode各个块(unicode_block)的信息。
collections
提供了除基础容器list,tuple,dict,set以外的容器,我比较常用的是namedtuple和defaultdict。defaultdict就是在赋值的时候不用手动初始化,考虑简单的计数问题(仅仅是实例,可以用counter)。
1 2 | c = collections.defaultdict(int) c[0] += 1 |
复杂一点的,如针对各个字符串统计各字符数的defaultdict,也就是defaultdict的defaultdict。
1 2 | d = collections.defaultdict(lambda :collections.defaultdict(int)) d['hello']['l'] += 1 |
array
与list类似,不过array的数据存储更加原生,而且array中的数据类型得一致,就像C/C++一样。看例子就明白了。
1 2 3 4 5 6 7 8 9 | import sys import array a = [x for x in range(10000)] b = array.array('i', a) print(sys.getsizeof(a[1])) # 28 print(sys.getsizeof(a)) # 87624 print(sys.getsizeof(b)) # 40064 |
此处我反正是搞不懂为啥a只用87624个bytes,这乘法不对啊。40064就容易理解多利,10000个整数,每个4 bytes,加上数据结构64 bytes,这个空间直接省了1半。当然也可以用numpy。
linecache
随机读取文件行,小文件可以,大文件直接内存爆炸。
timeit
规范的测试几行代码速度的工具,使用也很方便。
1 | python -m timeit "5+8" |
operator
我曾经一直不理解operator的用处,跟内置的运算符重复,实在没有,也可以使用lambda
。后来我搜索了一下,stackoverflow,stackoverflow2,给了我一点启示。主要出于速度、代码可读性、以及picklable考虑。关于速度可以简单测试如下,
1 2 3 4 5 6 | $ python -m timeit "5+8" 50000000 loops, best of 5: 5.61 nsec per loop $ python -m timeit -s "from operator import add" "add(5,8)" 10000000 loops, best of 5: 33.7 nsec per loop $ python -m timeit "(lambda x,y: x+y)(5,8)" 2000000 loops, best of 5: 107 nsec per loop |
itertools
与operator一样,属于函数式编程模块。借鉴了Haskell等语言的思想,实现了大量高效、内存友好的迭代工具,与operator相辅相成。官方介绍中也提供了很多例子。我用得最多的居然是chain.from_iterable(),我觉得我得改。takewhile
这些都很不错。
1 | itertools.takewhile(lambda x: x<5, [1,4,6,4,1]) |
functools
与上面两个一样,属于函数式编程模块。其中的lru_cache是比较典型的操作,能很好的解释functools。另外wraps也是常用的,其他几个我还没有使用过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import functools import time @functools.lru_cache(maxsize=1024) def fibonacci(n): if n<=1: return n return fibonacci(n-1)+fibonacci(n-2) start_time = time.time() fibonacci(100) print(time.time() - start_time) def fibonacci(n): if n<=1: return n return fibonacci(n-1)+fibonacci(n-2) start_time = time.time() fibonacci(32) print(time.time() - start_time) |
typing
使用type hints可以帮助我们在编码时就发现bug,当然借助的是ide的提示。mypy也可以进行代码检查,可以告知哪里类型有问题,可以及时发现处理。
1 2 | def greeting(name: str) -> str: return 'Hello ' + name |
其他
其他很多库,如heapq,bisect,re,threading,multiprocessing,profile,pdb,json等都是非常常用好用的库。如果能灵活使用这些库,必定能提供编码效率。此处效率包括编程速度和运行速度。估计我也就掌握了1/10左右。
每个半年回过头看自己写的老代码,总感觉非常羞耻,想推倒重来。我觉得这是好事,说明人还在进步学习。希望还能保持这个速度。
链接