1

So, basically, I have a code for python 2.7 like this:

femalebreeders = [[[0] * 4] * n] * pat
femalebreeders1 = [[[0] * 4] * n] * pat


for y in range(pat):
    for x in range(n):
            Indivmales[y][x] = malebreeders[y][x][0] + malebreeders[y][x][3]
    Fec1[y] = 1 - c * numpy.array(numpy.mean(Indivmales[y]))
    FecMales = numpy.ndarray.tolist(1 + (numpy.array(Indivmales) * b) - (numpy.array(Indivmales) * u))
    Fec = [0 if i < 0 else i for i in Fec1]
    FecPop = numpy.mean(Fec)
    FecCalcF[y] = (Fec[y] * (1 - mf)) / ((Fec[y] * (1 - mf)) + (FecPop * mf))
    FecCalcF2[y] = (Fec[y] * mf) / FecPop
    FecCalcM[y] = (Fec[y] * (1 - mm)) / ((Fec[y] * (1 - mm)) + (FecPop * mm))
    FecCalcM2[y] = (Fec[y] * mm) / FecPop


for x in range(n):
    for y in range(pat):
        if random.random() < FecCalcF[y]:
            z = y
        else:
            z = numpy.random.choice(pat, p=numpy.ndarray.tolist(numpy.array(FecCalcF2)/sum(FecCalcF2)))
        f = random.randrange(n)
        m = random.randrange(n)
        if random.random() < mut:
            if random.random() < 0.5:
                femalebreeders1[y][x][0] = femalebreeders[z][f][0] + \
                                               random.uniform(-1, 1)

Some background. n is number of individuals, pat is the number of patches where individuals are. FecCalcF and FecCalcF2 are just variables that say if individuals are going to migrate or not (let's assume that they always migrate to a new patch). So, I want to, for every individual, assign it a patch (y). And, because they always migrate, their parents come from another patch (z) and that depends on the fecundity of the individuals on each patch. In the end, I want to have different females that came from different patches. However, the values of the femalebreeders is something like ([0.10, 0, 0, 0], [0.10, 0, 0, 0] .... ]. Basically, the first value is always equal for all of them (and the same for the others values, I'm just showing part of it). Basically, it seems that the code gives them always the same value - which means that the parents are all the same and all from the same patch. Anyone knows what I'm doing wrong?

JackShh
  • 45
  • 7
  • where do you initialize `femalebreeders`? looks like you probably implemented all the lists with the same reference so changing one list will change all of them – R Nar Nov 18 '15 at 17:06
  • I initialise femalebreeders outside the loop and it's define like this: `femalebreeders1 = [[[0] * 4] * n] * pat` The 4 is because there are 4 alleles – JackShh Nov 18 '15 at 17:09
  • edit your question and add in the code where you initialise – R Nar Nov 18 '15 at 17:10
  • Possible duplicate of [why can't I change only a single element in a nested list in Python](http://stackoverflow.com/questions/10941032/why-cant-i-change-only-a-single-element-in-a-nested-list-in-python) – R Nar Nov 18 '15 at 17:33
  • Yeah, maybe. I'm really new with python. Should define femalebreeders like this then: `femalebreeders = [[[0] * 4] * n * pat for i in range(n)]` Because it's not working... – JackShh Nov 18 '15 at 17:53
  • 1
    replace all of your `*` with list comprehensions. so it would be `[[[0] * 4] for i in range(n)] for j in range(pat)]` – R Nar Nov 18 '15 at 17:58
  • Thanks, that worked! – JackShh Nov 19 '15 at 09:32

1 Answers1

0

Be careful initializing lists with the multiplication operator. If you do, you end up with a list containing multiple references to the same list. Here's a short bit of code as an example:

In [1]: list_1 = [[0] * 2] * 2

In [2]: list_1
Out[2]: [[0, 0], [0, 0]]

In [3]: list_1[0][0] = 99

In [4]: list_1
Out[4]: [[99, 0], [99, 0]]

You can see that the first and second item in list_1 are actually the same object by using the builtin id function:

In [5]: for item in list_1:print id(item)
139861322599744
139861322599744

Use a list comprehension instead:

In [6]: list_22 = [[0] * 2 for i in range(2)]

In [7]: list_2
Out[7]: [[0, 0], [0, 0]]

In [8]: list_2[0][0] = 99

In [9]: list_2
Out[9]: [[99, 0], [0, 0]]
Chris Lawlor
  • 47,306
  • 11
  • 48
  • 68