Python局部变量初始化

时间:2016-05-11 20:15:01

标签: python

我对python很新,我想知道局部变量是如何工作的。让我们从一个简单方法的例子开始:

def do_sth():
    local_dict = { 'a': 1, 'b': 2, 'c': 3, ... }
    ...

让我们假设local_dict像一个const变量一样使用。这就是问题:每次调用do_sth()或创建一次并将其保存在do_sth()内部的某个地方时都会创建它?

5 个答案:

答案 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文件时被声明和分配。

如果我错了,请纠正我。