Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

list of objects python

I am trying to print a list of python objects that contain a list as a property and i am having some unexpected results:

here is my code:

class video(object):

    name = ''
    url = ''

class topic(object):

    topicName = ''
    listOfVideo = []

    def addVideo(self,videoToAdd):
        self.listOfVideo.append(videoToAdd)

    def getTopic(self):
        return self.topicName

    def getListOfVideo(self):
        return self.listOfVideo


topic1 = topic()
topic1.topicName = 'topic1'
video1 = video()
video1.name = 'VideoName1'
video1.url = 'VideoURL1'

video2 = video()
video2.name = 'VideoName2'
video2.url = 'VideoURL2'
topic1.addVideo(video1)
topic1.addVideo(video2)

topic2 = topic()
topic2.topicName = 'topic2'

video3 = video()
video3.name = 'VideoName3'
video3.url = 'VideoURL3'

video4 = video()
video4.name = 'VideoName4'
video4.url = 'VideoURL4'

topic2.addVideo(video3)
topic2.addVideo(video4)

topicsList = []
topicsList.append(topic1)
topicsList.append(topic2)

for topicCurrent in topicsList:
    print(topicCurrent.topicName)
    for video in topicCurrent.getListOfVideo():
        print(video.name)
        print(video.url)

What I expect to get is this:

topic1

VideoName1

VideoURL1

VideoName2

VideoURL2

topic2

VideoName3

VideoURL3

VideoName4

VideoURL4

but what I actually get is this:

topic1

VideoName1

VideoURL1

VideoName2

VideoURL2

VideoName3

VideoURL3

VideoName4

VideoURL4

topic2

VideoName1

VideoURL1

VideoName2

VideoURL2

VideoName3

VideoURL3

VideoName4

VideoURL4

Why? I want to iterate over my list of topics and print out each video in each topic, but for each topic it prints out all videos???

What is going on here?

like image 423
user254340 Avatar asked Jul 19 '16 03:07

user254340


1 Answers

You have created class variables instead of instance variables, which are different for each instance object. Define your class as follows:

class topic(object):

    def __init__(self):
        self.topicName = ''
        self.listOfVideo = []

    def addVideo(self,videoToAdd):
        self.listOfVideo.append(videoToAdd)

    def getTopic(self):
        return self.topicName

    def getListOfVideo(self):
        return self.listOfVideo

From Python Tutorial:

Instance variables are for data unique to each instance and class variables are for attributes and methods shared by all instances of the class.

EDIT:

One more important thing to consider is that why only listOfVideo was common for all instances but not topicName. It is because list's are mutable objects while string's are immutable.

So any changes made to listOfVideo are common for all instances, i.e., they still refer to listOfVideo defined in the topic namespace.

However when you do topic1.topicName = 'topic1', you create a new variable topicName within topic1 namespace, which overrides the topicName found in topic(class) namespace. You can confirm it by printing the value topic.topicName, which you will find to be an empty string, i.e., ''.

like image 82
shiva Avatar answered Sep 26 '22 05:09

shiva