python 优化函数_Python小技巧 -- 性能优化篇

本文介绍了Python性能优化的一些关键技巧,包括循环优化如减少循环内的计算、避免点操作,语言优化如使用列表解析推导式、字典查找优于列表,以及字符串操作优化如使用join代替+。此外,还提到了集合操作、条件表达式的懒评估和关键字排序等方法,以提升代码效率。
摘要由CSDN通过智能技术生成

性能优化篇

1. 循环优化

a. 尽量减少循环内的计算,能循环外能实现的逻辑不放在循环内[2.22倍]

#坏的写法

data = [1,2,3,4,5,6,7]

for i in xrange(1000):

d_len = len(data) # 可在循环外实现

k = d_len + i

# 好的写法

data = [1,2,3,4,5,6,7]

d_len = len(data)

for i in xrange(1000):

k = d_len + i

b. 避免在循环中使用点操作

原因:每次调用obj.func时,python都会求该方法的值。所以可先用一个变量保存求得的值,避免循环每次求值

# 普通做法

lowerlist = ['this', 'is', 'lowercase']

upperlist = []

for word in lowerlist:

upperlist append(str.upper(word))

# 优化后做法

lowerlist = ['this', 'is', 'lowercase']

upperlist = []

upper = str.upper

append = upperlist.append

for word in lowerlist:

append(upper(word))

c. python2用xrange代替range

原因python2中xrange返回一个迭代器内存占用为常量,range返回一个数组内存占用大。注:python3中xrange不再存在,range返回一个迭代器。

2. 语言优化性能小技巧

a. 列表解析推导式优于for循环append构建 [3.3倍]

# 坏的写法

deamo_list = []

for i in xrange(10000):

deamo_list.append(i)

# 好的写法

deamo_list = [i for i in xrange(10000)]

c. 字典(dict)查找优于列表(list)

因为字典为hash表查找复杂度为O(1),list为数组复杂度为O(n)。当存在大量数据频繁查找时,将list转为dict是较好的选择。

# 一般做法

unsupport_items = ['a', 'b', 'is', 'python', 'jason', 'hello', 'hill', 'with', 'phone', 'test',

'dfdf', 'apple', 'pddf']

candicates = ['is', 'hat', 'new', 'list', 'old', '.']

target_items = []

for item in candicates:

if item not in unsupport_items:

target_items.append(item)

# 优化后写法

unsupport_items = ['a', 'b', 'is', 'python', 'jason', 'hello', 'hill', 'with', 'phone', 'test',

'dfdf', 'apple', 'pddf']

unsupport_items_dict = dict.fromkeys(unsupport_items, True) # list转为dict

candicates = ['is', 'hat', 'new', 'list', 'old', '.']

target_items = []

for item in candicates:

if item not in unsupport_items_dict:

target_items.append(item)

d. 集合(set)比列表(list)更适合做与集、交集、差集操作

set的union、intersection、difference操作比list的迭代要快。

e. 充分利用Lazy if-evaluation特性

大部分高级语言都支持条件表达式lazy evaluation特性。即if x and y表达式,如果x为false时y表达式值将不再计算。可将概率大、成本低、能快速确定条件表达式值的表达式放在前面,避免对低概率小或高成本表达式的计算。

# 一般做法

items = ['sss', 'bbb', 'ccc', 'tetasdfsdxx.txt', 'tet.txt', 'asdfa.pdf', 'xasdf.php']

txt_file = []

for item in iems:

if len(item) > 2 && item.endswith('.txt'):

txt_file.append(item)

# 好的写法

items = ['sss', 'bbb', 'ccc', 'tetasdfsdxx.txt', 'tet.txt', 'asdfa.pdf', 'xasdf.php']

txt_file = []

for item in iems:

if item.endswith('.txt') and len(item) > 2: # 通过判断.txt可快速过滤掉非文本文件,避免了对大量非txt文件名长度的无谓计算

txt_file.append(item)

f. if done is not None 比语句 if done != None更快

g. python的build in(内建)函数通常比较快

原因内建函数通常是经过语言特性优化的,性能较好。如:add(a, b)要优于 a + b

h. 使用关键字排序

使用关键字和默认的sort()方法排序,要优于自定义一个排序函数

# 例子:list

import operator

somelist = [(1, 5, 8), (6, 4, 5), (7, 3, 11)]

somelist.sort(key=operator.itemgetter(0)) # 按照第一个元素排序

somelist.sort(key=operator.itemgetter(1)) # 按照第二个元素排序

somelist.sort(key=operator.itemgetter(1)) # 按照第三个元素排序

# 例子:dict

import operator

somelist = [dict(a=1, b=2), dict(a=3,b=5),dict(a=44,b=33)]

somelist.sort(key=operator.attrgetter('a')) # 按照关键字'a'排序

somelist.sort(key=operator.attrgetter('b')) # 按照关键字'b'排序

i. 列表推导式

列表推导式优于for循环

# 普通写法:

alist = []

for i in xrange(10):

alist.append(i)

# 优化后写法1,[]生成一个列表:

alist = [i for i in xrange(10)]

# 优化后写法2, ()生成一个生成器:

alist_gen = (i for i in xrange(10))

# 优化后写法3,将生成器封装成一个方法

def seq_generator(amount):

return (i for x in xrange(amount))

for i in seq_generator(10):

print("index : %s" % i)

3. 字符串优化

a. 字符串操作join优于+或+=

因为python中字符串对象为不可变对象。对字符串的任何操作,如拼接、修改都会产生一个新的字符串对象,即产生持续的内存申请、copy操作,会对python性能有一定的影响。而join操作会先计算总内存量,一次性申请到位然后copy过去。join的内存申请次数少于+或+=,故性能更优。

# 不好的写法

items = ["I", "am", "from", "china"]

item_str = ""

for item in items:

item_str += item + " "

# 好的写法

items = ["I", "am", "from", "china"]

item_str = " ".join(items)

b. 当对字符串可以使用正则表达或内置函数来处理时,优先选择内置函数

如:str.isalpha()、str.isdigit()、str.startswitch(('x', 'xy'))、str.endswith(('x', 'xy'))

# 一般做法

import re

is_digit_reg = re.compile("^[0-9]$")

data_str = "123"

if is_digit_reg(data_str):

print("%s is digit" % data_str)

# 优化后做法:

data_str = "123"

if data_str.isdigit():

print("%s is digit" % data_str)

c. 对字符进行各耍比直接串联读取要快

原因:字符串的每次操作都会申请内存生成一个临时对象。

# 较好的写法

out_str = "%s from %s at time %s" % (name, city, date)

# 不好的写法

out_str = name + " from " + city + " at time " + date

合理使用生成器或yield

原因生成器对象所占内存空间大小和列表大小无关,故效率会较高些

4. 关键代码依赖于外部高性能包

即,利用C、C++等语言编写的喂不包,提高应用程序关键任务的性能。 但这些包通常不支持跨平台,移植性较差。如:Cython、PyInIne(python应用程序中直接使用C代码)、PyPy、Pyrex.

多使用cpython模块.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值