hidemyname
hidemyname

Reputation: 4287

How to understand the variable scope in python?

def gibsSample(pB,pC,pA_B,pD_BC,pE_D,pF_C,label_A,label_B,label_C,label_D,label_E,label_F,T):
    #initial state
    sample=['A=F','B=n','C=F','D=h','E=F','F=F']
    sampleState=[]
    for i in range(T):
        #draw sample A from p(A | B,C,D,E,F)
        sample_A=sampleA(sample,pA_B)
        sample[0]=sample_A
        #draw sample B from p(B | A,C,D,E,F)
        sample_B=sampleB(sample,pB,pA_B,pD_BC)
        sample[1]=sample_B
        #draw sample C from p(C | A,B,D,E,F)
        sample_C=sampleC(sample,pC,pD_BC,pF_C)
        sample[2]=sample_C
        #draw sample D from p(D | A,B,C,E,F)
        sample_D=sampleD(sample,pD_BC,pE_D)
        sample[3]=sample_D
        #draw sample E from p(E | A,B,C,D,F)
        sample_E=sampleE(sample,pE_D)
        sample[4]=sample_E
        #draw sample F from p(F | A,B,C,D,E)
        sample_F=sampleF(sample,pF_C)
        sample[5]=sample_F
        sampleState.append(sample)
    return sampleState

I wrote a sample algorithm. Every time after I sampled from one distribution, the element in variable 'sample' will be modified and after a circle, I want to append it in the list 'sampleState'. But why it seems the 'sampleState' only appended the initial 'sample' but not the sample I modified? I iterated the loop for 2000 times and all the elements in 'sampleState' are just the same with the initial state, but I checked the 'sample' in every iteration there was no problem.

Upvotes: 0

Views: 53

Answers (2)

Martin Konecny
Martin Konecny

Reputation: 59601

Everytime you append sample to the list, you are appending a reference to the exact same object.

After each loop you are changing the values inside this object (the value at each index of the sample list), so if all objects in your list point to the same object, they will all see the same value.

To fix this, create a new list at the end of each loop:

    def gibsSample(pB,pC,pA_B,pD_BC,pE_D,pF_C,label_A,label_B,label_C,label_D,label_E,label_F,T):
        #initial state
        sample=['A=F','B=n','C=F','D=h','E=F','F=F']
        sampleState=[]
        for i in range(T):
            #draw sample A from p(A | B,C,D,E,F)
            sample_A=sampleA(sample,pA_B)
            sample[0]=sample_A
            #draw sample B from p(B | A,C,D,E,F)
            sample_B=sampleB(sample,pB,pA_B,pD_BC)
            sample[1]=sample_B
            #draw sample C from p(C | A,B,D,E,F)
            sample_C=sampleC(sample,pC,pD_BC,pF_C)
            sample[2]=sample_C
            #draw sample D from p(D | A,B,C,E,F)
            sample_D=sampleD(sample,pD_BC,pE_D)
            sample[3]=sample_D
            #draw sample E from p(E | A,B,C,D,F)
            sample_E=sampleE(sample,pE_D)
            sample[4]=sample_E
            #draw sample F from p(F | A,B,C,D,E)
            sample_F=sampleF(sample,pF_C)
            sample[5]=sample_F
            sampleState.append(list(sample)) # here you create a copy of your "sample"
        return sampleState

Alternate solution

Because you are using a list of a fixed size, you may also want to use a 6-tuple:

def gibsSample(pB,pC,pA_B,pD_BC,pE_D,pF_C,label_A,label_B,label_C,label_D,label_E,label_F,T):
    #initial state
    sample=('A=F','B=n','C=F','D=h','E=F','F=F')
    sampleState=[]
    for i in range(T):
        #draw sample A from p(A | B,C,D,E,F)
        sample_A=sampleA(sample,pA_B)

        #draw sample B from p(B | A,C,D,E,F)
        sample_B=sampleB(sample,pB,pA_B,pD_BC)

        #draw sample C from p(C | A,B,D,E,F)
        sample_C=sampleC(sample,pC,pD_BC,pF_C)

        #draw sample D from p(D | A,B,C,E,F)
        sample_D=sampleD(sample,pD_BC,pE_D)

        #draw sample E from p(E | A,B,C,D,F)
        sample_E=sampleE(sample,pE_D)

        #draw sample F from p(F | A,B,C,D,E)
        sample_F=sampleF(sample,pF_C)

        t = (sample_A, sample_B, sample_C, sample_D, sample_E, sample_F)
        sampleState.append(t)
    return sampleState

Upvotes: 1

akarilimano
akarilimano

Reputation: 1074

What you are looking for is static variables in functions. As it described in this question, you need to replace sample with gibsSample.sample everywhere in your code:

def gibsSample(pB,pC,pA_B,pD_BC,pE_D,pF_C,label_A,label_B,label_C,label_D,label_E,label_F,T):
    #initial state
    gibsSample.sample=['A=F','B=n','C=F','D=h','E=F','F=F']
    sampleState=[]
    for i in range(T):
        #draw sample A from p(A | B,C,D,E,F)
        sample_A=sampleA(gibsSample.sample,pA_B)
        gibsSample.sample[0]=sample_A
        #draw sample B from p(B | A,C,D,E,F)
        sample_B=sampleB(gibsSample.sample,pB,pA_B,pD_BC)
        gibsSample.sample[1]=sample_B
        #draw sample C from p(C | A,B,D,E,F)
        sample_C=sampleC(gibsSample.sample,pC,pD_BC,pF_C)
        gibsSample.sample[2]=sample_C
        #draw sample D from p(D | A,B,C,E,F)
        sample_D=sampleD(gibsSample.sample,pD_BC,pE_D)
        gibsSample.sample[3]=sample_D
        #draw sample E from p(E | A,B,C,D,F)
        sample_E=sampleE(gibsSample.sample,pE_D)
        gibsSample.sample[4]=sample_E
        #draw sample F from p(F | A,B,C,D,E)
        sample_F=sampleF(gibsSample.sample,pF_C)
        gibsSample.sample[5]=sample_F
        sampleState.append(gibsSample.sample)
        gibsSample.sample = [None] * 6
    return sampleState

Upvotes: 0

Related Questions