Skip to content
Advertisement

dictionary update – very strange behaviour

When running below code, the dict shows unexpected behaviour

I a nutshell, I select a date in the past and add the information to a dict about that date. All is well until I print the resulting dict after all the iterations:

functioning code, you can C/V this into your shell and run it with dictTester():

from calendar import datetime as calendar_date
from datetime import datetime
def dictTester():
    breakdowns_dict = {}
    for row in range(2):
        temp_list = [row, None, None]
        while_true_counter = 0
        date_extracted = datetime.now() - calendar_date.timedelta(days=row)
        date_extracted = datetime.strptime(date_extracted.strftime('%Y-%m-%d'),'%Y-%m-%d')
        date_now = datetime.strptime(datetime.now().strftime('%Y-%m-%d'),'%Y-%m-%d')
        while True:
            if date_extracted > date_now:
                print('date > now')
                print('break')
                break
            if date_extracted == date_now:
                print('date == now')
                temp_list[1] = date_extracted.strftime('%Y-%m-%d')
                if while_true_counter > 0:
                    temp_list[2] = 'RIGHT'
                else:
                    temp_list[2] = 'PURE'
                print(temp_list)
            if date_extracted < date_now:
                print('date < now')
                temp_list[1] = date_extracted.strftime('%Y-%m-%d')
                if while_true_counter > 0:
                    temp_list[2] = 'MIDDLE'
                else:
                    temp_list[2] = 'LEFT'
                print(temp_list)
            if date_extracted not in breakdowns_dict:
                breakdowns_dict[date_extracted] = {}
                print('created entry')
            else:
                print('updated entry')
            print(date_extracted)
            print(len(breakdowns_dict[date_extracted]))
            breakdowns_dict[date_extracted][len(breakdowns_dict[date_extracted])] = temp_list
            print(breakdowns_dict[date_extracted][len(breakdowns_dict[date_extracted])-1])
            # next iteration
            date_extracted += calendar_date.timedelta(days=1)
            while_true_counter += 1    
    for bd_date in breakdowns_dict:
        for bd_entry in breakdowns_dict[bd_date]:
            print(bd_date.strftime('%Y-%m-%d'), breakdowns_dict[bd_date][bd_entry])

python shell output

$ date == now     
$ [0, '2021-03-18', 'PURE']     
$ created entry '2021-03-18' 0 = [0, '2021-03-18', 'PURE']    
$ date > now     
$ break     
$ date < now     
$ created entry 2021-03-17 0 = [1, '2021-03-17', 'LEFT']     
$ date == now    
$ updated entry '2021-03-18' 1 = [1,'2021-03-18', 'RIGHT']     
$ date > now break

So you would expect the result dict to be:

$ '2021-03-18' 0 = [0, '2021-03-18', 'PURE']
$ '2021-03-18' 1 = [1,'2021-03-18', 'RIGHT']
$ '2021-03-17' 0 = [1, '2021-03-17', 'LEFT']

But instead it prints:

$ '2021-03-18' [0, '2021-03-18', 'PURE'] 
$ '2021-03-18' [1, '2021-03-18', 'RIGHT'] 
$ '2021-03-17' [1, '2021-03-18', 'RIGHT'] 

and you can see more of this funky behaviour when increasing the row value

for 3 you should get a ‘PURE’ a ‘LEFT’-‘RIGHT’ and a ‘LEFT’-‘MIDDLE’-‘RIGHT’ and so on, you get the idea

but that would be disregarding the adversary.

Advertisement

Answer

The simple bug was a pass by reference vs pass by value error, silly me

as answered here: python list by value not by reference

updating the code line:

breakdowns_dict[date_extracted][len(breakdowns_dict[date_extracted])] = temp_list

to

breakdowns_dict[date_extracted][len(breakdowns_dict[date_extracted])] = temp_list[:]

was all that was required

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement