'Changing the parameters of elements in a list individually
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]
Solution 1:[1]
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)]
Solution 2:[2]
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
Solution 3:[3]
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Zelemist |
| Solution 3 | Maxime Lavaud |
