我对python很新,我想知道局部变量是如何工作的。让我们从一个简单方法的例子开始:
def do_sth():
local_dict = { 'a': 1, 'b': 2, 'c': 3, ... }
...
让我们假设local_dict像一个const变量一样使用。这就是问题:每次调用do_sth()或创建一次并将其保存在do_sth()内部的某个地方时都会创建它?
答案 0 :(得分:6)
您可以使用dis
模块查看解释器的作用:
def do_sth():
d = {'a':2, 'b':3}
print(id(d))
import dis
dis.dis(do_sth)
将打印
2 0 BUILD_MAP 2
3 LOAD_CONST 1 (2)
6 LOAD_CONST 2 ('a')
9 STORE_MAP
10 LOAD_CONST 3 (3)
13 LOAD_CONST 4 ('b')
16 STORE_MAP
17 STORE_FAST 0 (d)
3 20 LOAD_GLOBAL 0 (id)
23 LOAD_FAST 0 (d)
26 CALL_FUNCTION 1
29 PRINT_ITEM
30 PRINT_NEWLINE
31 LOAD_CONST 0 (None)
34 RETURN_VALUE
表明每次调用函数时解释器都在重建值。
答案 1 :(得分:3)
每次调用do_sth()
时。这很重要,因为它允许您对函数内的local_dict
进行修改,并且不会对其他调用产生任何影响。解释器不够智能,看你是否不会改变它,特别是因为Python是如此动态,以至于有一些非常迂回的方式可以让它改变。
在这里,您可以向自己证明字典不断重新创建:
def print_3():
print(3)
def do_sth():
local_dict = {'a': print_3()}
do_sth()
do_sth()
do_sth()
打印3到3次。
我认为全局变量可以很好地优化它,但如果你真的想要,那怎么样:
def do_sth():
return do_sth.local_dict
do_sth.local_dict = {'a': print_3()}
从技术上讲,每个人仍然可以访问它,但它更清楚它属于什么。
答案 2 :(得分:1)
局部变量始终在函数范围内创建。一旦程序计数器退出函数(局部变量的范围),就由垃圾收集器收集。
global_dict = []
def do_sth():
local_dict = { 'a': 1, 'b': 2, 'c': 3, ... }
...
def do_other_task():
#local_dict not visible. It's outside of scope.
global global_dict # fetch memory address of previously declared global_dict
global_dict = { 'a': 1, 'b': 2, 'c': 3, ... }
答案 3 :(得分:1)
使用is
运算符检查很容易:
def test():
return {'a': 1, 'b': 2, 'c': 3}
>>> test() is test() #did both produce the same object in memory space?
False
这对于可变对象很有意义,或mutable default argument陷阱会出现在各处。
但是有些值存储为常量,可以使用dis
看到这些值,因为常量加载了LOAD_CONST
字节代码:
>>> dis.dis(lambda:1)
1 0 LOAD_CONST 1 (1)
3 RETURN_VALUE
>>> dis.dis(lambda:(1,True, 10*1000, "a"))
1 0 LOAD_CONST 7 ((1, True, 10000, 'a'))
3 RETURN_VALUE
>>> dis.dis(lambda:[1,2,3]) #list is mutable
1 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 LOAD_CONST 3 (3)
9 BUILD_LIST 3
12 RETURN_VALUE
>>> dis.dis(lambda:{"a":1}) #dict is also mutable
1 0 LOAD_CONST 1 ('a')
3 LOAD_CONST 2 (1)
6 BUILD_MAP 1
9 RETURN_VALUE
答案 4 :(得分:0)
其他答案都是正确的,我只想补充一下。
在这种情况下,我宁愿做:
constant_dict = { 'a': 1, 'b': 2, 'c': 3, ... }
def do_sth():
# do something reading constant_dict
do_sth()
或但不太优选:
def do_sth(local_dict = { 'a': 1, 'b': 2, 'c': 3, ... }):
# do something reading local_dict
do_sth()
在这两种情况下,python都不必重新分配变量的内存,因为它在解释器读取python文件时被声明和分配。
如果我错了,请纠正我。