Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Why different datatypes as class attribute behave differently?

Why is it that when I assign a new value to class attribute which is of type 'int', it does not affect new instances of the class. While when I change value of a type 'list', all of the instances that will be created will follow?

Consider class Human:

class Human:
    health = 100
    posessions = []

    def __init__(self, name):
        self.name = name

And execution:

print("Instatiate object anne as Human: ")
anne = Human("Anne")
# print anne instance's health attribute, I expect:
# Health = 100, Posessions = 0
print("anne.name = {}".format(anne.name))
print("anne.health = {}".format(anne.health)) # OK
print("Number of posessions= ".format(len(anne.posessions)), end="\n\n")

print("Change object anne's attributes: ")
# change and print anne instance's health attribute, I expect:
# Health = 95, Possessions: 3
anne.health = 95
anne.posessions.append("guitar")
anne.posessions.append("notebook")
anne.posessions.append("phone")
print("anne.name = {}".format(anne.name))
print("anne.health = {}".format(anne.health))# OK
print(len(anne.posessions)) # OK
print("Number of posessions: ".format(len(anne.posessions)))
for ps in  anne.posessions:
    print(ps)
print("\n")

print("Create new instance carlou as Human")
carlou = Human("Carlou")
# print carlou instance's health attribute, I expect
# Health: 100, Possession = 0
print("carlou.name = {}".format(carlou.name))
print("carlou.health = {}".format(carlou.health)) # OK
print(len(carlou.posessions)) # ???
print("Number of posessions: ".format(len(carlou.posessions))) # ???
for ps in  carlou.posessions:
    print(ps)

Results:

Instatiate object anne as Human: 
anne.name = Anne
anne.health = 100
Number of posessions= 

Change object anne's attributes: 
anne.name = Anne
anne.health = 95
3
Number of posessions: 
guitar
notebook
phone


Create new instance carlou as Human
carlou.name = Carlou
carlou.health = 100
3
Number of posessions: 
guitar
notebook
phone

Ideally, in results, I expect the length of carlou instance's posession is 0, but it carried anne's length and content.

Could somebody clarify the reason behind this?

Thanks!

1 Answer

I'm unclear on all the aspects of classes, but it is the way the list is initialized. If you move posessions into the init, so it gets initialized when a new instance is created it seems to work. If I was to guess why health and posessions are different. Most variable are just pointers to memory locations. Health assigns a value every time, but posessions is open. It may be passing the memory location that is assigned to that variable.

class Human:
    health = 100
    def __init__(self, name):
        self.name = name
        self.posessions = []

Thanks William!

That is correct. Instantiating a class variable inside init solves the problem.

I also found the complete explanation from here, by karl-knechtel (though not the answer that was selected as the best):

List as a member of a python class, why is its contents being shared across all instances of the class?

Thanks again! :blush: