Nobi
Nobi

Reputation: 1109

Appending to a list within a function that is called implicitly

In this code, the generate() function is called implicitly by another function.

The question is as follows, in the code below is there a way to ensure that when the generate() function is called for instance 4 times in this case, values of b is saved in list p without replacing the preceding element appended to it, currently only one value of b is appended to t.

    import random as rand 
    f = [1,2,3,4]
    k = rand.choice(f)
    h = rand.choice(f)


    def generate():

        global b # declare b as global

        t = []
        b = k + h
        t.append(b) #Append b to all so that
        print 'all:',t

        c = 4**2

        return c

generate()


def evaluate():

    fit = (generate() * b) # generate() is used here

    print "fit:", fit

    # Some other expressions using variable b
    p = []
    for i in range(4):
        p.append(b)
    print 'p:',p

    return fit

evaluate()


#output
all: [3]
fit: 48
p: [3, 3, 3, 3]

Upvotes: 2

Views: 1614

Answers (2)

Peter Gibson
Peter Gibson

Reputation: 19544

I think you have a scope problem. Read up on scoping in Python with the links below and consider this example:

>>> results = []
>>> i = [0]
>>> def test():
...     i[0] = random.randint(0, 100)
...     print i
...     results.append(i)
...
>>> test()
[20]
>>> test()
[99]
>>> test()
[18]
>>> results
[[18], [18], [18]]

Note that even though the value of i[0] changes for each call to test(), we are appending the same list i to results each time - so when an element in i changes, the changes are reflected throughout the results list.

Links:

Short Description of the Scoping Rules?

https://www.inkling.com/read/learning-python-mark-lutz-4th/chapter-17/python-scope-basics

EDIT

To fix the above problem, you need to make sure you're not overwriting the same list in each call to test(). You can do this by creating a new list each time, or by copying the list before modifying it

>>> import copy
>>> def test():
...     j = copy.copy(i)
...     j[0] = random.randint(0, 100)
...     print j
...     results.append(j)
...
>>> results = []
>>> test()
[75]
>>> test()
[13]
>>> test()
[17]
>>> results
[[75], [13], [17]]

You mention that you are dealing with nested lists, in which case you should use copy.deepcopy instead of copy.copy. Deep copy will make copies of all of the elements in the list as well as the list itself.

Upvotes: 3

Joran Beasley
Joran Beasley

Reputation: 113940

t would need to be global ...

of coarse it only has one element you initialize it as empty and then append one item to it ... also its only available within the generate function ....

its also very unclear what you are trying to accomplish with generate (typically it would return a new individual...)

you can fix it so that t gets all the b's like so ...

t = []
def generate():
    global b # declare b as global
    b = k + h
    t.append(b) #Append b to all so that
    print 'all:',t
    c = 4**2
    return c

although I suspect you have alot more problems than that

Upvotes: 1

Related Questions