python进阶用法3 【优化毫不起眼的

2023-01-31 05:01:31 优化 进阶 用法

这篇博客提及三个关于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、仅仅分别产生generatorlist对象

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是一个全局变量,而非关键字

相关文章