Most data types in python are immutable, including integers
a = 2
b = a # a and b refer to the same memory location, storing the value 2
b = 5 # b now points to a new memory location, storing the value 5
print a, b
# result: 2 5
# a still points to the old memory location
Some data types, such as lists and sets, are mutable
x = [2]
y = x # x and y refer to the same memory location, storing a list [2]
y[0] = 5 # Updating list y modifies the list in place, the list is mutable
print x, y
# [5] [5] # Both x and y are sharing the same memory
This causes unexpected behaviour in some cases, such as in classes. This happens because the aliases
data structure is referenced from all instances of the class. The name
is unaffected because it is immutable; when the name
is changed the object is modified to point to a new memory location.
class Person(object):
name = ''
aliases = []
steve = Person()
steve.name = 'Steven'
steve.aliases.append('Steve')
alice = Person()
alice.name = 'Alice'
alice.aliases.append('Allie')
print steve.name, "is also known as", steve.aliases
# Result: Steven is also known as ['Steve', 'Allie']
print alice.name, "is also known as", alice.aliases
# Result: Alice is also known as ['Steve', 'Allie']
The solution for this is to initialise your member variables in the constructor:
class Person(object):
def __init__(self):
self.name = ''
self.aliases = []
steve = Person()
steve.name = 'Steven'
steve.aliases.append('Steve')
alice = Person()
alice.name = 'Alice'
alice.aliases.append('Allie')
print steve.name, "is also known as", steve.aliases
# Result: Steven is also known as ['Steve']
print alice.name, "is also known as", alice.aliases
# Result: Alice is also known as ['Allie']
The aliases
list is now created for each instance of the Person
class, so your objects behave independently of each other.