Python 代码性能优化技巧

Python代码性能优化技巧

代码优化能够让程序运行更快,优化通常包含两方面:减小代码的体积,提高代码的运行效率。

1 优化包含多个判断语句顺序

将相对逻辑比较简单的放在前面优先判断,对于and,应该把满足条件少的放在前面,
对于or,把满足条件多的放在前面

from timeit import timeit
#判断语句顺序不同 代码执行的效率也不一样
print timeit('[i for i in range(1000) if 10 <i<20 or 200<i<1000]', number=1000)
print timeit('[i for i in range(1000) if 200<i<1000 or 10<i<20]', number=1000)
print timeit('[i for i in range(1000) if i<990 and i%3==0]', number=1000)
print timeit('[i for i in range(1000) if i%3==0 and i<990]', number=1000)

2 利用return 优化条件判断缩进

def role_fun(role):
	if role.get_level() >= 0:
		if role.get_money() >= 100:
			if role.get_reputation() >= 999:
				role.do_buy()
#将上面这种写法优化为
def opt_role_fun(role):
	if role.get_level < 0:
		return
	if role.get_money() < 100:
		return
	if role.get_reputation() < 999:
		return
	role.do_buy()

类似的,当遇到for + 条件判断时,可以用continue优化缩进

def opt_role_fun():
	for role in cGameServer.GetAllRole():
		if role.get_level() >= 0:
			if role.get_money() >= 100:
				if role.get_reputation() >= 999:
					role.do_buy()

#将上面代码优化
def opt_role_fun():
	for role in cGameServer.GetAllRole():
		if role.get_level < 0:
			continue
		if role.get_money() < 100:
			continue
		if role.get_reputation() < 999:
			continue
		role.do_buy()

3 对循环优化

尽量减少循环过程中的计算量,有多重循环的尽量将内层的计算提到上一层

from time import time 
L1 = [i for i in range(1000)] 
L2 = [i for i in range(10)]

for _ in range (1000): 
    for x in range(len(L1)): 
        for y in range(len(L2)): 
            v=L1[x]+L2[y] 
#将循环次数多的放最外层,避免在循环体内最重复的运算
#Python2 使用xrange 代替range
length_1=len(L1) 
length_2=len(L2)
for _ in xrange (1000): 
    for x in xrange(length_2): 
        temp=L2[x] 
        for y in xrange(length_1): 
            v=temp+L1[y] 

4 查找次数比较多,尽量使用dict或者set

python dict和set都是使用hash表来实现,查找元素的时间复杂度是O(1)
而 list 实际是个数组,查找需要遍历整个 list,其复杂度为 O(n),因此对成员查找访问等操作字典、集合要比 list 更快

from time import time 
t = time() 
L1 = ['a','b','c','Python','c++']
L2 = [chr(i) for i in range(97,123)]
#L2= dict.fromkeys(L2,True)	#这里将list转成dict,大大提高代码效率
l= [] 
for _ in range (1000000): 
    for x in L1: 
        if x not in L2: 
            l.append(x) 
print "total run time:"
print time()-t

5 set 和 list

set 的 union,intersection,difference 操作要比 list 的迭代要快。因此如果涉及到求 list 交集,并集或者差的问题可以转换为 set 来操作。

L1 = ['a','b','c','Python','c++']
L2 = [chr(i) for i in range(97,123)]
for _ in xrange(1000):
	ret = list(set(L1)&set(L2))
#set 常见用法
set(L1)|set(L2)  #union			L1、L2所有元素的集合
set(L1)&set(L2)  #intersection	L1、L2交集
set(L1)-set(L2)  #difference	L1中非L2的元素集合

6 使用列表解析和生成器表达式

[chr(i) for i in range(97,123)]
[(x,y) for x in range(3) for y in range(10)]
#慎用这种
{key:val for key in [chr(s) for s in range(97,123)] for val in range(97,123)}

7 对字符串使用的优化

python 中的字符串对象是不可改变的,因此对任何字符串的操作如拼接,修改等都将产生一个新的字符串对象,而不是基于原字符串,因此这种持续的 copy 都会在一定程度上影响 python 的性能

<1>字符串的拼接尽可能使用join 而不是 ‘+’

s = "" 
# 尽量避免:
for x in str_list:
	s += func(x)
# 而是使用:
s_list = [func(elt) for elt in str_list]
s = ''.join(s_list)

<2>同时可以使用内置函数或者正则表达式的时候,优先选择后者比如str.startswith、str.endswith

<3>格式化字符串方式

#常用的几种格式化字符串方式 效率略有不同 按照速度排列如下
#选择合适自己的一种方式 保持代码风格一致性 个人比较喜欢%
out = "<html>" + head + prologue + query + tail + "</html>"
out = "<html>%s%s%s%s</html>" % (head, prologue, query, tail)
out = "<html>{}{}{}{}</html>".format(head,prologue,query,tail)

8 浅拷贝

生成一个序列副本,可以用copy与切片特性
切片就是序列抽取部分的操作,切片操作得到的对象和原对象是不同的对象,切片相当于浅拷贝

import copy
List = [0,1,2,3]
L1 = copy.copy(List)
L2 = List[:]	#使用切片的效率更高

9 变量值交换

# x, y 直接交换
x, y = y, x
# 而不是借助中间变量
t = x; x = y; y = t

10 使用if is/ if is not

if xx == True: -->if xx is True: 
if xx != True: --> if xx if not True:

11 级联比较

start < x < end  #这种写法效率略高,而且可读性更佳

12 善于利用for+else

def find_card(card_id)
	has_found = False
	for idx, card in enumerate(card_pool):
		if card_id == card.get_card_id():
			#找到的处理逻辑
			pass
			has_found = True
			break
	else:
		# 没有找到的处理逻辑
		pass
	#其他...
	pass
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值