killerwhale
killerwhale

Reputation: 37

How to bond dictionary key with global variable in python?

import threading
from time import sleep


v1 = 100
dictionary = {'key':v1}

def fn1():
    global v1
    for i in range(30):
        sleep(0.2)
        v1 = i

def fn2():
    global dictionary # this line is totatlly unnecessary, I know 
    for i in range(30):
        sleep(0.2)
        print(dictionary['key'])

th1 = threading.Thread(target=fn1)
th1.start()
th2 = threading.Thread(target=fn2)
th2.start()

This code outputs only 100's, I would want it to output 1, 2, 3 ... Changing value in dictionary is not really a solution - it needs to work in a quite more complex situation, but will rewrite if necessary

Thanks!

Upvotes: 1

Views: 119

Answers (2)

quamrana
quamrana

Reputation: 39404

One option you have is to have some indirection:

v1 = [100]
dictionary = {'key':v1}

def fn1():
    global v1
    for i in range(30):
        sleep(0.2)
        v1[0] = i

def fn2():
    global dictionary # this line is totatlly unnecessary, I know 
    for i in range(30):
        sleep(0.2)
        print(dictionary['key'][0])

This uses a list to hold the integer as the first item.

Now the dict holds a reference to a list which is the same list all the time.

Upvotes: 1

Koto
Koto

Reputation: 511

To provide a little more insight as to what is happening: When you create the dictionary v1 points to 100 and the reference to the value 100 is copied to the dictionary dictionary = {'key':v1}

>>> d={'key':v1}
>>> id(v1)
140715103675136
>>> id(d['key'])
140715103675136

As you can see both v1 and the dict point at the same location in the memory.

In the loop you then change the reference where v1 points to and once it is finished it will point to where Python stores the value 29. However the loop never updates the reference where your dictionary points to.

If you want to change the value of the dictionary you could use a mutable type, such as a list and then pop the elements.

v1 = [100]
dictionary = {'key': v1}
def fn1():
  global v1
  for i in range(30):
    sleep(0.2)
    v1.append(i)
    #or: v1[0] = i

def fn2():
  global dictionary # this line is totatlly unnecessary, I know 
  for i in range(30):
    sleep(0.2)
    print(dictionary['key'].pop[0])
    #or:print(dictionary['key'][0])

Upvotes: 2

Related Questions