-1

I've the following class structure:

class StarCount:
    one_stars = 0
    two_stars = 0
    three_stars = 0
    four_stars = 0
    five_stars = 0

class OrientationAnalysis:
    straight = StarCount()
    bisexual = StarCount()
    gay = StarCount()

class GenderAnalysis:
    men = OrientationAnalysis()
    women = OrientationAnalysis()

I've written the following code:

genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100

print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is also 100

Why genderanalysis.women.straight.five_stars is also updated? I've checked the genderanalysis.women.gay.five_stars also but it's not updated?

Nayan
  • 1,521
  • 2
  • 13
  • 27

4 Answers4

3

Define the values in the init methods of the classes, so that they become attached to intance objects, not the class object itself.

class StarCount:
    def __init__(self):
        self.one_stars = 0
        self.two_stars = 0
        self.three_stars = 0
        self.four_stars = 0
        self.five_stars = 0

class OrientationAnalysis:
    def __init__(self):
        self.straight = StarCount()
        self.bisexual = StarCount()
        self.gay = StarCount()

class GenderAnalysis:
    def __init__(self):
        self.men = OrientationAnalysis()
        self.women = OrientationAnalysis()

genderanalysis = GenderAnalysis()
genderanalysis.men.straight.five_stars = 100

print genderanalysis.men.straight.five_stars # outputs 100
print genderanalysis.women.straight.five_stars # this is now 0
hoodakaushal
  • 1,253
  • 2
  • 16
  • 31
3

When you declare some variables like this:

class StarCount:
    one_stars = 0
    two_stars = 0
    three_stars = 0
    four_stars = 0
    five_stars = 0

These variables become class variables. Class variables are variables that are shared by all instances of a class. So when you updated genderanalysis.men.straight.five_stars, it actually updated StarCount.five_stars and as genderanalysis.women.straight.five_stars also points to the same variable, it seemed to have updated too.

I think what you are looking for are instance variables. You can declare them like this:

class StarCount:
    def __init__(self):
        self.one_stars = 0
        self.two_stars = 0
        self.three_stars = 0
        self.four_stars = 0
        self.five_stars = 0

Edit

Why genderanalysis.women.gay.five_stars is not updated?

What happens is that before you updated any variable of genderanalysis object, all of the variables were pointing to the variables of StarCount class. As you can see they have same id:

print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229389744'
print(id(genderanalysis.women.gay.five_stars)) # prints '94016229389744'

But when you changed genderanalysis.men.straight.five_stars, the reference/pointer got replaced with your provided value, in this case 100. You can see difference in their id's:

print(id(StarCount.five_stars)) # prints '94016229389744'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', see the difference?

So now genderanalysis.men.straight.five_stars does not point to StarCount.five_stars, rather it points to OrientationAnalysis.straight.five_stars. Once again, let's check their id's:

print(id(OrientationAnalysis.straight.five_stars)) # prints '94016229391328'
print(id(genderanalysis.men.straight.five_stars)) # prints '94016229391328', same right?

Now onto your question, at this point genderanalysis.women.gay.five_stars is still untouched so it points to StarCount.five_stars and so it still prints 0. Change StarCount.five_stars and you can see the change reflecting in genderanalysis.women.gay.five_stars.

StarCount.five_stars = 101
print(genderanalysis.women.gay.five_stars) # prints `101`
Mezbaul Haque
  • 1,242
  • 9
  • 13
1

your attributes should not be class attributes but instance attributes instead. this would be a start for you:

class StarCount:
    def __init__(self, five_stars=0):

        self.five_stars = five_stars
        # ...


class OrientationAnalysis:
    def __init__(self):

        self.straight = StarCount()
        # ...


class GenderAnalysis:
    def __init__(self):

        self.men = OrientationAnalysis()
        self.women = OrientationAnalysis()
hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
0

you’re almost there— you are referencing and modifying class variables rather than instance variables.

You need an __init__(self) method, and to create all the attributes on self

Maus
  • 1,791
  • 1
  • 17
  • 28