0

This is an uncluttered version of this question. Since I changed so much I made a new question

I am trying to take certain values from a longer array solution and put them into a smaller array, within an object. This code is supposed to take the first half of the solution array and put it into x_hist within m1, and the second half of the solution array and put it into x_hist within m2. Instead it appears to take all of the solution array and put it into x_hist for both objects. Anyone know why this may be the case? Have I accidentally vectorized the code?

class Mass:
    x_hist = []

m1 = Mass()
m2 = Mass()
ms = [m1,m2]

solution = [1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0]

for i in range(len(ms)):
    for k in range(int(len(sol)/len(ms))):
        ms[i].x_hist.append(solution[k+8*i])

print(m1.x_hist)
print(m2.x_hist)

The output is:

[1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0]

I am trying to get an output of:

[1, 2, 3, 4, 5, 6, 7, 8]
[0, 0, 0, 0, 0, 0, 0, 0]
bnosnehpets
  • 172
  • 10

3 Answers3

5

x_hist property is static class property

variables Declared inside classes are static variables different from the context of instance which means,

>>> s = M()
>>> s
<__main__.M object at 0x7f9ffb4a6358>
>>> s.i
3
>>> M.i
3
>>> s.i = 4
>>> M.i
3
>>> s.i
4



class Mass:
    #x_hist = [] shared by all classes its static
    def __init__(self):
        self.x_hist = []

m1 = Mass()
m2 = Mass()
ms = [m1,m2]

solution = [1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0]

for i in range(len(ms)):
    for k in range(int(len(sol)/len(ms))):
        ms[i].x_hist.append(solution[k+8*i])

print(m1.x_hist)
print(m2.x_hist)

For static Method and ClassMethod check Here

For Nice Tutorial for Classes Refer Here

Akash
  • 2,795
  • 1
  • 7
  • 11
  • Looks like @Akash beat me to it - nice answer. A nice SO question on [static class variables](https://stackoverflow.com/questions/68645/are-static-class-variables-possible) for the interested. – FChm Mar 04 '19 at 13:23
  • Thanks, problem with transferring from Java! – bnosnehpets Mar 04 '19 at 13:24
1

I suspected the following was the case, but I don't fully understand yet. Essentially, your class construction is not correct: x_hist was never declared as an attribute of the Mass() class. So it was just appending to (I assume) the globally declared x_hist.

class Mass():
    def __init__(self):
        self.x_hist = []

m1 = Mass()
m2 = Mass()
ms = [m1, m2]

solution = [1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0]

for i in range(len(ms)):
    for k in range(int(len(solution)/len(ms))):
        ms[i].x_hist.append(solution[k+8*i])

print(m1.x_hist)
print(m2.x_hist)

Returns:

[1, 2, 3, 4, 5, 6, 7, 8]
[0, 0, 0, 0, 0, 0, 0, 0]
FChm
  • 2,515
  • 1
  • 17
  • 37
0

The problem is basically in the nested loops! once the first iteration of the outer loop is done, you restart the inner loop so you basically append the first half in both lists.

It's better to rewrite the loops, for readability:

step = int(len(solution)/len(ms))
for m, k in zip(ms, range(0,len(solution), step)):
    m.x_hist.extend(solution[k : k+step])
print(m1.x_hist)
print(m2.x_hist)
[1, 2, 3, 4, 5, 6, 7, 8]
[0, 0, 0, 0, 0, 0, 0, 0]

EDIT:

The class attribute shared by all instances mentioned above can be accessed by:

Mass.x_hist

And this will contain all solution elements. If you simply try to access the x_hist of an instance, you are correct to access through m1.x_hist but you should probably not use class variables unless necessary.

nickyfot
  • 1,932
  • 17
  • 25