Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python loop dictionary value references updating all values

I am having a problem updating values in a dictionary in python. I am trying to update a nested value (either as an int or list) for a single fist level key, but instead i update the values, for all first level keys.

I start by creating the dictionary:

kmerdict = {}
innerdict = {'endcover':0, 'coverdict':{}, 'coverholder':[], 'uncovered':0, 'lowstart':0,'totaluncover':0, 'totalbases':0}
for kmer in kmerlist: # build kmerdict
    kmerdict [kmer] = {}
    for chrom in fas:  #open file and read line
        chromnum = chrom[3:-3]
        kmerdict [kmer][chromnum] = innerdict

Then i am walking through chromosomes (as plain text files) from a list (fas, not shown), and taking 7mer strings (k=7) as the key. If that key is in a list of keys i am looking for (kmerlist) and trying to use that to reference a single value nested in the dictionary:

for chrom in fas:  #open file and read line
    chromnum = chrom[3:-3]
    p = 0  #chromosome position counter
    thisfile = "/var/store/fa/" + chrom
    thischrom = open(thisfile)
    thischrom.readline()
    thisline = thischrom.readline()
    thisline = string.strip(thisline.lower())
    l=0  #line counter
    workline = thisline
    while(thisline):
        if len(workline) > k-1:
            thiskmer = ''
            thiskmer = workline[0:k] #read five bases
            if thiskmer in kmerlist:
                thisuncovered = kmerdict[thiskmer][chromnum]['uncovered']
                thisendcover =  kmerdict[thiskmer][chromnum]['endcover']
                thiscoverholder = kmerdict[thiskmer][chromnum]['coverholder']
                if p >= thisendcover:
                    thisuncovered += (p - thisendcover)
                    thisendcover = ((p+k) + ext)
                    thiscoverholder.append(p)
                elif p < thisendcover:
                    thisendcover = ((p+k) + ext)
                    thiscoverholder.append(p)
            print kmerdict[thiskmer]
            p += 1
            workline = workline[1:]
        else:
            thisline = thischrom.readline()
            thisline = string.strip(thisline.lower())
            workline = workline+thisline
            l+=1
print kmerdict

but when i print the dictionary, all "thiskmer" levels are getting updated with the same values. I'm not very good with dictionaries, and i can't see the error of my ways, but they are profound! Can anyone enlighten me?

Hope i've been clear enough. I've been tinkering with this code for too long now :(

like image 931
krupton Avatar asked Oct 21 '25 11:10

krupton


1 Answers

confession -- I haven't spent the time to figure out all of your code -- only the first part. The first problem you have is in the setup:

kmerdict = {}
innerdict = {'endcover':0, 'coverdict':{}, 'coverholder':[], 'uncovered':0, 
             'lowstart':0,'totaluncover':0, 'totalbases':0}
for kmer in kmerlist: # build kmerdict
    kmerdict [kmer] = {}
    for chrom in fas:  #open file and read line
        chromnum = chrom[3:-3]
        kmerdict [kmer][chromnum] = innerdict

You create innerdict once and then proceed to use the same dictionary over an over again. In other words, every kmerdict[kmer][chromnum] refers to the same objects. Perhaps changing the last line to:

kmerdict [kmer][chromnum] = copy.deepcopy(innerdict)

would help (with an appropriate import of copy at the top of your file)? Alternatively, you could just move the creation of innerdict into the inner loop as pointed out in the comments:

def get_inner_dict():
    return {'endcover':0, 'coverdict':{}, 'coverholder':[], 'uncovered':0, 
            'lowstart':0,'totaluncover':0, 'totalbases':0}

kmerdict = {}
for kmer in kmerlist: # build kmerdict
    kmerdict [kmer] = {}
    for chrom in fas:  #open file and read line
        chromnum = chrom[3:-3]
        kmerdict [kmer][chromnum] = get_inner_dict()

-- I decided to use a function to make it easier to read :).

like image 83
mgilson Avatar answered Oct 23 '25 01:10

mgilson