How much memory does a function with yield use?
我很难理解
我会用例子来解释我的疑问。假设我们有三个功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 |
如果我迭代第一个函数返回的生成器,那么这个巨大的范围是否实际存储在内存中?
第二个函数呢?
如果我迭代第三个函数返回的生成器(而不仅仅是生成字典并直接迭代它),我的程序会使用更少的内存吗?
python 2
如果生成的结果是根据需要计算出来的,那么生成函数可以节省内存,但是
你可以计算下一个数字:
1 2 3 4 5 | def function1(): i = 0 while i < HUGE_NUMBER: yield i i += 1 |
你会得到同样的结果,但你不会一次存储整个范围的所有数字。这基本上就是循环遍历
这同样适用于您的
1 2 3 4 5 6 7 8 9 10 | 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 |
号
这只存储为避免重复而看到的键(就像字典那样),但不存储值。当您在生成器上迭代时,内存会增加。如果重复项不是问题,则可以完全忽略跟踪看到的键:
1 2 3 4 5 | def function3(file): with open(file, 'r') as f: reader = csv.reader(f, delimiter = ' ') for k, v in reader: yield k, v |
甚至
1 2 3 4 | def function3(file): with open(file, 'r') as f: reader = csv.reader(f, delimiter = ' ') return reader |
。
毕竟,读者是无可辩驳的。
生成器对象包含对函数作用域的引用,并通过扩展包含函数内所有本地对象。减少内存使用的方法是在每一个可能的级别上使用迭代器,而不仅仅是在顶层。
如果您想检查一个对象使用了多少内存,您可以将本文作为一个代理。我觉得它很有用。
"试试这个:
1 | sys.getsizeof(object) |
getsizeof()调用对象的sizeof方法,如果对象由垃圾收集器管理,则会添加额外的垃圾收集器开销。"
递归配方