这篇博客提及三个关于python循环
的优化细节,如有其他一些优化的方案,欢迎留言分享~QWQ
在谈这个环节之前,我们先回顾一波何为生成器及何为yield
要理解yiled还需要理解生成器,而要理解生成器,首先需要理解迭代器。
迭代器:
所有你可以用在for...in...
语句中的都是可迭代的:比如lists
,strings
,files
…因为这些可迭代的对象你可以随意的读取所以非常方便易用,但是你必须把它们的值放到内存里,当它们有很多值时就会消耗太多的内存.
生成器:
生成器也是迭代器的一种,但是你只能迭代它们一次.原因很简单,因为它们不是全部存在内存里,它们只在要调用的时候在内存里生成,下面看两个例子:
1、生成器
>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
... print(i)
...
0
1
4
>>>
2、list列表
>>> listTest = [x*x for x in range(3)]
>>> for i in listTest:
... print(i)
...
0
1
4
区别:
>>> print(listTest)
[0, 1, 4]
>>> print(mygenerator)
<generator object <genexpr> at 0x000001FAB703DE60>
生成器和迭代器的区别就是用()
代替[]
,还有你不能用for i in mygenerator
第二次调用生成器:首先计算0,然后会在内存里丢掉0去计算1,直到计算完4.
Yield
Yield
的用法和关键字return
差不多,下面的函数将会返回一个生成器:
>>> def createGenerator():
... mylist = range(3)
... for i in mylist:
... yield i*i
...
>>> mygenerator = createGenerator()
>>> print(mygenerator)
<generator object createGenerator at 0x000001FAB703DE60>
>>>
要理解Yield
你必须先理解当你调用函数的时候,函数里的代码并没有运行.函数仅仅返回生成器对象,这就是它最微妙的地方。
下面看两个例子:
1、仅仅分别产生generator
与list
对象
import time
import sys
t1 = time.time()
arange = (i for i in range(2000000))
print("brange size:")
print(sys.getsizeof(arange))
t2 = time.time()
print("arange time:")
print(t2-t1)
t3 = time.time()
brange = [i for i in range(2000000)]
print("brange size:")
print(sys.getsizeof(brange))
t4 = time.time()
print("brange time:")
print(t4-t3)
# brange size:
# 88
# arange time:
# 0.0
# brange size:
# 17632632
# brange time:
# 0.12857437133789062
使用()
得到的是一个generator
对象,所需要的内存空间与列表的大小无关,所以效率会高一些。至于原理见上面的生成器原理部分。
2、供for
循环使用
import time
t1 = time.time()
arange = (i for i in range(20000000))
for x in arange:
pass
t2 = time.time()
print("arange time:")
print(t2-t1)
t3 = time.time()
brange = [i for i in range(20000000)]
for x in brange:
pass
t4 = time.time()
print("brange time:")
print(t4-t3)
# arange time:
# 1.7372145652770996
# brange time:
# 1.8086597919464111
这里虽然说并没有快上多少,但不要忘记了,在时间更优的情况下,生成器generator
内存空间占用更是完爆list
,所以说,循环尽量用生成器!!!!
这个其实不必多说和解释,循环之外能做的事不要放在循环内,比如下面的优化基本可以快一倍:
import time
test = "123"
length_test = len(test)
t1 = time.time()
arange = (i for i in range(4000000))
for x in arange:
ap = length_test
t2 = time.time()
print("arange time:")
print(t2-t1)
t3 = time.time()
brange = (i for i in range(4000000))
for x in brange:
bp = len(test)
t4 = time.time()
print("brange time:")
print(t4-t3)
# arange time:
# 0.460693359375
# brange time:
# 0.8602120876312256
2333,这个你可能不相信,但请看例子:
import time
def while_1():
t1 = time.time()
n = 100000000
while 1:
n -= 1
if n <= 0: break
t2 = time.time()
print("while1 time:")
print(t2-t1)
def while_true():
t3 = time.time()
n = 100000000
while True:
n -= 1
if n <= 0: break
t4 = time.time()
print("while_true time:")
print(t4-t3)
if __name__ == '__main__':
while_1()
while_true()
# while1 time:
# 5.369367837905884
# while_true time:
# 5.293442487716675
至于原理:
True是一个全局变量,而非关键字