简体   繁体   中英

Accessing a List inside a class as part of a dictionary in Python

I am facing a weird issue with lists in Python. If it were C++, I would have thought of something in the lines of memory allocation errors that might have caused this

I have a dictionary of objects. Each of the objects has a list that has been initialized.

Once the dictionary has been been created and the objects initialized, I try to access a list belonging to one of the items in the dictionary. For some strange reason I seem to have inadvertently used the same list to create the second and third objects in the dictionary causing the same list to be printed for the other objects as well.

Can someone please help me out if possible?

Here is my code:

import random

class ClassOne ():
name = ""
arrayToPrint = []

def __init__(self):
    print("initialized class object")
    name = ""
    arrayToPrint = []

class ClassTwo:
    nameTwo =""


x= {}
#Initializing the dictionary
for i in range(3): #Creating a dictionary with 3 items in it
 classOne= ClassOne()
 classOne.name = str(i)
 #wanted to create each of the lists with random lengths
 numberOfarraysToAdd =random.randint(1,9)
 print ("number of arrayToPrint for class %d = %d" % (i, numberOfarraysToAdd))
 for j in range(numberOfarraysToAdd):
     #Initializing the list within the dictionary
     classTwo = ClassTwo()
     classTwo.nameTwo = random.randint(1,20)
     classOne.arrayToPrint.append(classTwo)
 x[i] = classOne #Copying the object of classOne into the dictionary with key as i
 classOne = None

#Getting the code to print the dictionary and list
for i in x: #traversing the dictionary
 print ("class name = %s" % x[i].name)
 print ("arrayToPrint = [")
 for j in range(len(x[i].arrayToPrint)-1): #traversing the list within the dictionary item
    print ("f(%d) = %s\t" % (j, x[i].arrayToPrint[j].nameTwo))
 print ("]")

Here is the output that I got. If you observe the f(0) to f(21) is the same for all the classes. This tells me that Python is using the same list across all items in the dictionary, or did I do something wrong?

initialized class object
number of arrayToPrint for class 0 = 9
initialized class object
number of arrayToPrint for class 1 = 7
initialized class object
number of arrayToPrint for class 2 = 7
class name = 0
arrayToPrint = [
f(0) = 17   
f(1) = 14   
f(2) = 10   
f(3) = 4    
f(4) = 19   
f(5) = 9    
f(6) = 9    
f(7) = 13   
f(8) = 11   
f(9) = 14   
f(10) = 19  
f(11) = 7   
f(12) = 6   
f(13) = 13  
f(14) = 1   
f(15) = 16  
f(16) = 1   
f(17) = 4   
f(18) = 6   
f(19) = 15  
f(20) = 6   
f(21) = 4   
]
class name = 1
arrayToPrint = [
f(0) = 17   
f(1) = 14   
f(2) = 10   
f(3) = 4    
f(4) = 19   
f(5) = 9    
f(6) = 9    
f(7) = 13   
f(8) = 11   
f(9) = 14   
f(10) = 19  
f(11) = 7   
f(12) = 6   
f(13) = 13  
f(14) = 1   
f(15) = 16  
f(16) = 1   
f(17) = 4   
f(18) = 6   
f(19) = 15  
f(20) = 6   
f(21) = 4   
]
class name = 2
arrayToPrint = [
f(0) = 17   
f(1) = 14   
f(2) = 10   
f(3) = 4    
f(4) = 19   
f(5) = 9    
f(6) = 9    
f(7) = 13   
f(8) = 11   
f(9) = 14   
f(10) = 19  
f(11) = 7   
f(12) = 6   
f(13) = 13  
f(14) = 1   
f(15) = 16  
f(16) = 1   
f(17) = 4   
f(18) = 6   
f(19) = 15  
f(20) = 6   
f(21) = 4   
]

Thanks in advance for any help

Yes, the instance of your list arrayToPrint is a class variable, and is thus shared. Use this to fix this behaviour:

class ClassOne ():
    def __init__(self):
        print("initialized class object")
        self.name = ""
        self.arrayToPrint = []

Beside this, the last two lines of your __init__ functions don't do anything - they create local variables that just have accidentally a common name with the class variables, and that disappear right after. So for the record, this is how you correctly access class variables:

class X:
    classVariable = 0

    def __init__(self):
        X.classVariable += 1
        self.anotherExampleOfAnInstanceVariable = 0

        aLocalVariableNoOneWillEverKnowAbout = ":("

It looks like you are having a problem with the differences in how classes are declared in C++ and Python:

To use assign a value to the attributes of your class with the init method you must:

def __init__(self, name, array_to_print):  # note Python uses lists/dictionaries not arrays and you should use underscores instead of pascalCase
    self.name = name
    self.array_to_print = array_to_print 

Anything declared outside the __init__ method will be shared among all instances of the same class.

class Foo:
    name = 'Ian'

    def __init__(self):
        blah blah

Every instance of the Foo class will have an attribute called name and it will be set to 'Ian' for all instances.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM