Python性能优化建议

来源:互联网 发布:康佳lc47d560dc 网络 编辑:程序博客网 时间:2024/05/16 03:33

1. 减少时间复杂度
在python中可以选取合适的数据结构来优化时间复杂度,比如list和set查找某一个元素的时间复杂度分别为O(n)和O(1)。
2. 合理安排and和or前后表达式的顺序
and:应该把满足条件的表达式放在前面,的放在后面
or:应该把满足条件的放在前面,的放在后面
3. 合理使用copy与deepcopy
cope为浅复制
deepcopy为深复制,采用递归复制的方式
效率方面,copy优于deepcopy
注意: 针对list和dict这类可变变量,直接赋值采用的是引用的方式,如果想要复制整个对象,则需要使用copy和deepcopy。
当要复制的对象为复合对象时,copy与deepcopy才有所不同。
复合对象的例子:[1,2,3,{1:2},[12,1]]
复制复合对象时,如果使用copy,则复制当前对象,并将内部对象的引用插入其中,如果使用deepcopy,则复制该对象,并复制内部对象插入其中。
所以,当复制的对象不是复合对象时,使用copy的效率要高,当复制的对象是符合对象时,并且需要当复合对象内部对象改变时并不影响原始的对象,则必须用deepcopy。
例如:

>>> a = [1,2,3,4]>>> b = a>>> a[1, 2, 3, 4]>>> b[1, 2, 3, 4]>>> a.append(5)>>> a[1, 2, 3, 4, 5]>>> b[1, 2, 3, 4, 5]>>> from copy import copy,deepcopy>>> b = copy(a) # 仅复制第一层元素的对象>>> a[1, 2, 3, 4, 5]>>> b[1, 2, 3, 4, 5]>>> a.append(6)>>> a[1, 2, 3, 4, 5, 6]>>> b[1, 2, 3, 4, 5]>>> c = [1,2,[1,2,3]]>>> d = copy(c)>>> e = deepcopy(c) # 复制所有对象>>> d[1, 2, [1, 2, 3]]>>> e[1, 2, [1, 2, 3]]>>> c[2].append(4)>>> c[1, 2, [1, 2, 3, 4]]>>> d[1, 2, [1, 2, 3, 4]]>>> e[1, 2, [1, 2, 3]]

4.合理使用生成器(generator)和yield

>>> a = (i for x in range(1000))>>> a<generator object <genexpr> at 0x7fd526969be0>>>> b = [i for i in range(1000)]

使用()可以生成generator对象,生成a所需时间比生成b所需时间要少,因为generator所占内存大小与列表的大小无关,因此效率要高一些。python2.x中可以生成generator对象的内置函数有xrange和itertools包。
但是, 使用如果需要循环遍历,则情况恰好相反,使用生成器的循环效率要低于普通的list或tuple。但是如果循环里有break,使用generator较好。可以用yield创建生成器,方法如下:

>>> def generate_list(n):...      for i in n:...         print i...         yield i+1... >>> generate_list([1,2,3,4])<generator object generate_list at 0x7faf586816e0>>>> for x in generate_list([1,2,3,4]):...     print "**",x... 1** 22** 33** 44** 5>>> 

从上面可以看出,每循环一次,都会访问一次生成器,生成本次循环所需的元素。
5. 格式化字符串
有三种格式化字符串的方式:
(1)%
(2)format
(3)+
三种方式相比,+最快,format次之,%最差,但是速度相差不大。

>>> a, b = "hello", "world">>> "%s %s"%(a, b)'hello world'>>> "{0} {1}".format(a, b)'hello world'>>> a + " " + b'hello world'>>> 

6.使用正确的序列化和反序列化方式
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
有三种反序列化的方式:eval()、json.loads()和cPickle.loads()
eval:不安全,对用户传递过来的参数使用eval进行反序列化,如果参数中是可执行命令,则对造成系统不安全。
速度方面,json>cPickle>eval
7. 使用dict和set 查找元素
python的dict和set都是用hash表来实现,查找元素的时间复杂度是O(1)。
8. 减少冗余数据
如用上三角或下三角的方式去保存一个大的对称矩阵。在0元素占大多数的矩阵里使用稀疏矩阵表示。
9. 调用用c实现的接口
10. 并行执行,多线程多进程
11. 优化循环
能在循环之外执行的语句不要放在循环之内
12. 使用join连接迭代器中的字符串
join()函数的参数可以试迭代对象,也可以是迭代器。该方式优于累加的方式。
累加的方式指:

>>> s = ["hello", "world", "!"]>>> s1 = "">>> for s2 in s:...     s1 += s2... >>> s1'helloworld!'>>> 

使用join:

>>> s = ["hello", "world", "!"]>>> s1 = " ".join(s)>>> s1'hello world !'>>> s = iter(s)>>> s1 = " ".join(s)>>> s1'hello world !'>>> 

13.不利用中间变量交换两个元素的值
例如:

>>> a, b = 1, 2>>> a, b = b, a>>> a2>>> b1>>> 

14.使用级联比较x<y<z而不是x<y and y<z
15.使用is来判断变量是否为True或False要比用==快
python2.x中True和False为全局变量,并不是关键字,True为1,False为0,值可以被更改,即可以写成True = 0, False = 1,在python3.x中才被设置为关键字。
16.python2.x中使用while 1要比while True快
17.使用**计算指数要比pow函数要快

>>> s = 2**3>>> s8>>> s = pow(2,3)>>> s8
原创粉丝点击