iCa*_*arn 3 python memory yield generator
我无法理解yield关键字.
我理解程序执行时会发生什么影响,但我真的不明白它使用了多少内存.
我将尝试用例子来解释我的怀疑.
假设我们有三个功能:
HUGE_NUMBER = 9223372036854775807
def function1():
for i in range(0, HUGE_NUMBER):
yield i
def function2():
x = range(0, HUGE_NUMBER)
for i in x:
yield i
def function3(file):
with open(file, 'r') as f:
dictionary = dict(csv.reader(f, delimiter = ' '))
for k,v in dictionary.iteritems():
yield k,v
Run Code Online (Sandbox Code Playgroud)
如果我迭代第一个函数返回的生成器,那么巨大的范围是否实际存储在内存中?
第二个功能怎么样?
如果我迭代第三个函数返回的生成器,那么我的程序会使用更少的内存(而不是仅仅创建该字典并直接迭代它)吗?
Python 2 range()函数生成的巨大列表需要存储,是的,并将占用内存,在生成器函数的整个生命周期内.
发电机的功能可以是内存使用效率,提供其生产需要的计算结果,但range()函数生成所有结果前面.
你可以计算下一个数字:
def function1():
i = 0
while i < HUGE_NUMBER:
yield i
i += 1
Run Code Online (Sandbox Code Playgroud)
并且你会得到相同的结果,但你不会一次性存储整个范围的所有数字.这基本上是xrange()对象的循环; 它根据要求计算数字.(在Python 3中xrange()取代range()).
这同样适用于您function3; 您首先将整个文件读入字典,以便在迭代时仍然存储在内存中.之后不需要将整个文件读入内存中以生成每个元素.你可以循环遍历文件并产生线:
def function3(file):
seen = set()
with open(file, 'r') as f:
reader = csv.reader(f, delimiter = ' ')
for k, v in reader:
if k in seen:
# already seen
continue
seen.add(k)
yield k, v
Run Code Online (Sandbox Code Playgroud)
这只存储了可以避免重复的密钥(就像字典一样)但是没有存储值.迭代生成器时内存会增加.如果重复项不是问题,您可以省略完全跟踪看到的键:
def function3(file):
with open(file, 'r') as f:
reader = csv.reader(f, delimiter = ' ')
for k, v in reader:
yield k, v
Run Code Online (Sandbox Code Playgroud)
甚至
def function3(file):
with open(file, 'r') as f:
reader = csv.reader(f, delimiter = ' ')
return reader
Run Code Online (Sandbox Code Playgroud)
毕竟,读者是可迭代的.
| 归档时间: |
|
| 查看次数: |
1320 次 |
| 最近记录: |