I want to change a parameters in a list of elements QF and QD as following: Lattice is a list includes these elements for example :
lattice = [QF, QD, QF, QD]
And the indexes of these elements in the list are given in quad_indexes.
QF and QD has two parameters (K and FamName):
QF.K = 1.7 and QD.K = -2.1
QF.FamName = 'QF'
QD.FamName = 'QD'
I want to gave the random value for the parameter K for each element individually
I tried:
i =0
Quad_strength_err =[]
while(i < len(quad_indexes)):
if(lattice[quad_indexes[i]].FamName == 'QF'):
lattice[quad_indexes[i]].K *= (1 errorQF*random())
i = 1
elif(lattice[quad_indexes[i]].FamName == 'QD'):
lattice[quad_indexes[i]].K *= (1 errorQD * random())
i = 1
for j in quad_indexes:
quad_strength_err = lattice[j].K
Quad_strength_err.append(quad_strength_err)
The problem is when i print (Quad_strength_err) i got fixed value for each of QF and QD, for example:
[1.8729820159805597, -2.27910323371567, 1.8729820159805597, -2.27910323371567]
I am looking foe a result for example:
[1.7729820159805597, -2.17910323371567, 1.8729820159805597, -2.27910323371567]
CodePudding user response:
TL;DR
You need to make copies of QF and QD - you're making aliases.
The problem
The problem is almost certainly due to aliasing.
When you initialize lattice
with this line:
lattice = [QF, QD, QF, QD]
what you are doing is creating a structure with two pointers to QF
and two pointers to QD
.
In your loop, you then modify QF
twice, once via lattice[0]
and again via lattice[2]
, and ditto for QD
.
The solution
What you need to do is create copies, maybe shallow, maybe deep.
Try this option:
from copy import copy
lattice = [copy(QF), copy(QD), copy(QF), copy(QD)]
and if that still doesn't work, you might need a deepcopy:
from copy import deepcopy
lattice = [deepcopy(QF), deepcopy(QD), deepcopy(QF), deepcopy(QD)]
Or, a more compact version of the same code, just cause I like comprehensions:
from copy import deepcopy
lattice = [deepcopy(x) for x in (QF, QD, QF, QD)]
CodePudding user response:
If your code is correct, you can't expect a different result for your first and third element of lattice
(resp second and last), since it's (to simplify) the same element.
Using id
, you can easily show that, lattice[0]
and lattice[2]
share the same id, therefore modifying lattice[0]
will modify lattice[2]
.
You can duplicate each object QF and QD to git rid of this behavior
CodePudding user response:
I tryed to build a working sample of your problem starting by building simple QF
and QD
classes :
from random import random
class QF():
def __init__(self):
self.K = 1.7
self.FamName = "QF"
class QD():
def __init__(self):
self.K = -2.1
self.FamName = "QD"
then I create the lattice with different instance of the classis by calling them with ()
lattice = [QF(), QD(), QF(), QD()]
I think your mistake comes from this step as QF
refers to the class it self and QF
creats a brand new instance that you can modify separatly from the other one. For example if you do QF.K = 3
and then a = QF()
, a.K
should return you 3
.
finally I apply some randomness using the random
imported previously :
for i in lattice:
if i.FamName == "QF":
i.K = (1 errorQF*random())
elif i.FamName == "QD":
i.K = (1 errorQD*random())
form which I get :
print(*[i.K for i in lattice])
>>>> 1.148989048860669 0.9324164812782919 1.0652187255939742 0.6860911849022292