这一直困扰着我。我想知道分配变量和调用方法的比较内存效率。例如,考虑一下:
s =" foo"
x = s.lower()
对战
x =" foo" .lower()
在内存使用方面哪一个更有效?
这显然是一个微不足道的例子,但它说明了我对此感到疑惑
我们在很多实例中定义了一些变量var1 = foo
,然后定义了第二个变量var2 = var1.method()
。整个过程是否需要更多内存而不仅仅是定义var2 = foo.method()
?
答案 0 :(得分:2)
第一种情况下字节码较大,但只有很少的数量。
$ python3
Python 3.3.5 (default, Mar 9 2014, 08:10:50)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> def f():
... s = "foo"
... x = s.lower()
... return x
...
>>> def g():
... x = "foo".lower()
... return x
...
>>> dis.dis(f)
2 0 LOAD_CONST 1 ('foo')
3 STORE_FAST 0 (s)
3 6 LOAD_FAST 0 (s)
9 LOAD_ATTR 0 (lower)
12 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
15 STORE_FAST 1 (x)
4 18 LOAD_FAST 1 (x)
21 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_CONST 1 ('foo')
3 LOAD_ATTR 0 (lower)
6 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
9 STORE_FAST 0 (x)
3 12 LOAD_FAST 0 (x)
15 RETURN_VALUE
>>>
(令人遗憾的是,CPython 仍然在字节编译时甚至没有做基本的CSE或copyprop,但这是一个完整的问题。 。)
在第一种情况下,运行时内存要求也略大,因为该函数有两个可变插槽而不是一个,但字符串本身不会复制额外的时间。 Python始终如一地使用引用语义。
编辑:正如cdonts指出的那样,如果代码更复杂且变量不会立即超出范围,则第一个版本会保持原始字符串在堆上保持活动状态,直到{ {1}}超出了范围, 可能是一个重要的额外内存成本。我甚至都没有想到这一点。
答案 1 :(得分:1)
在您的第一个示例中,s
仍在内存中,直到垃圾收集器删除它,因此您的第二个示例在内存使用方面更有效。但是,考虑到这只是RAM的一小部分,在许多情况下最好是为了提高可读性(第一个例子看起来更好)。
希望这有帮助。