[Python]Python高级编程
想来每隔一段时间都要写点关于python编程的博客。不知不觉已经写了一些,具体如下:
回调函数,线程安全,Monkey Patch和try/except使用
这里再写一篇,每隔一段时间总觉得python写的不够强,很多地方可以优化。这篇博客更多的是《Effective Python-编写高质量Python代码的59个有效方法》的读书笔记,作者是Google的Brett Slatkin。
(1)itertools的使用
在NER任务中,当得到pos对应的label之后,需要进一步得到entity,这个时候就可以使用itertools中的groupby来实现。如下:
label = [(0,'B-PER'),(1,'I-PER'),(2,'I-PER'),(3,'B-ORG')]
for tag, chunk in groupby(label, lambda x:x[1].split('-')[1]):
print(tag, ','.join(k for w, k in chunk))
输出如下:
PER B-PER,I-PER,I-PER
ORG B-ORG
(2)生成器表达式(dataloader中可以使用,yield)
warning:从身边的反馈来看,生成器的使用不当也会带来一些奇怪的问题。
可以避免内存用量问题,同时串在一起的生成器表达式执行速度很快。代码如下:
it = (len(x) for x in open('data.txt'))
roots = ((x,x**0.5) for x in it)
print(next(roots))
(3)用列表推导来取代map和filter
(4)遵循pep8风格指南
a.使用space(空格)来表示缩紧,而不要用tab(制表符)
b.判断somelist是否为[]或者‘’等空值,不要使用
if len(somelist) == 0
而是使用
if not somelist
(5)try/except/pdb的使用方式(书中建议:尽量使用异常来表示特殊情况,而不要返回None)
三者结合的新方式,如下:
try:
#step0
except:
import pdb;pdb.set_trace()
else:
#step1
(6)考虑用生成器来改写直接返回列表的函数(节约内存的大杀器,dataloader实现需关注)
(7)按照列表中字符串的长度给列表进行排序
names = ['zhpmatri','zhp','matrix']
sorted(names, key=lambda x: len(x))
(8)并发和并行(在数据处理的相关任务中可以重点关注)
a.用subprocess模块来管理子进程
b.可以用线程来执行阻塞式I/O,但不要用它做平行计算
c.在线程中使用Lock来防止数据竞争
d.用Queue来协调各线程之间的工作
e.考虑用协程来并发地运行多个函数
f.考虑用concurrent.futures来实现真正的平行计算
(9)eval来执行一个字符串表达式,使用repr输出一个来自logging的值,可以最大化地保持值本身的信息
(10)性能分析
python提供了两种内置性能分析器,分别叫做profile和cProfile。后者会更好一些,使用后者时对受测程序的效率只会产生很小的影响。而前者会产生较大的开销,使得测试结果变得不准确。
(11)内存使用和泄漏
tracemalloc
总结:比起用Python做后台研发,算法方面对Python的特性需求感觉并不是很高。这应该与两个不同工种的工作流有关。多数情况下,模型代码往往有几个文件组成,即使是框架,也并不需要相对复杂的语言特性。但是对特性的了解,可以帮助我们写出更fancy,更pythonic的code吧。
其他的高效方法:
1.Python 3 Quick Tip: The easy way to deal with file paths on Windows, Mac and Linux
os.path.join是最好的路径拼接的方法吗,不是的,pathlib。