Skip to content Skip to sidebar Skip to footer

Python Local Variable Initialization

I'm rather new to python and I'm wondering how local variables work. Let's start with an example of a simple method: def do_sth(): local_dict = { 'a': 1, 'b': 2, 'c': 3, ... }

Solution 1:

You can look at what the interpreter does using the dis module:

defdo_sth():
    d = {'a':2, 'b':3}
    print(id(d))


import dis
dis.dis(do_sth)

will print

20 BUILD_MAP                23 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)

  320 LOAD_GLOBAL              0 (id)
             23 LOAD_FAST                0 (d)
             26 CALL_FUNCTION            129 PRINT_ITEM          
             30 PRINT_NEWLINE       
             31 LOAD_CONST               0 (None)
             34 RETURN_VALUE        

which shows that the interpreter is rebuilding the value every time the function is called.

Solution 2:

Every time do_sth() is invoked. This is important because it allows you to make modifications to local_dict inside the function and it won't have any effect on other calls. The interpreter is not smart enough to see if you won't change it, especially because Python is so dynamic that there are some very roundabout ways you can cause it to change.

Here's how you can prove to yourself that the dictionary keeps getting recreated:

defprint_3():
    print(3)

defdo_sth():
    local_dict = {'a': print_3()}

do_sth()
do_sth()
do_sth()

This prints 3 ... 3 times.

I think global variables are fine for optimising this, but if you really want, how about this:

def do_sth():
    return do_sth.local_dict

do_sth.local_dict = {'a': print_3()}

Technically this can still be accessed by everyone but it's clearer what it belongs to.

Solution 3:

Local variable are always created in the scope of a function. There are collected by the garbage collector once the program counter quits function (scope of the local variable).

global_dict = []

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

defdo_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, ... }

Solution 4:

it would be easy to check with the is operator:

deftest():
    return {'a': 1, 'b': 2, 'c': 3}

>>> test() is test() #did both produce the same object in memory space?False

This makes a lot of sense for mutable objects or the mutable default argument trap would come up everywhere.

However there are values that are stored as constants and those can be seen using dis as constants are loaded with the LOAD_CONST byte code:

>>>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

Solution 5:

The other answers are correct, I would just add this.

I would rather do, in such case, either:

constant_dict = { 'a': 1, 'b': 2, 'c': 3, ... }
def do_sth():
    # do something reading constant_dict

do_sth()

or but less preferable:

defdo_sth(local_dict = { 'a': 1, 'b': 2, 'c': 3, ... }):
    # do something reading local_dict

do_sth()

In both cases, python would not have to reallocate the memory for the variable, because it got declared and allocated when the interpreter reads the python file.

Correct me if I'm wrong.

Post a Comment for "Python Local Variable Initialization"