473,327 Members | 2,065 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,327 software developers and data experts.

Confuzed about class variables vs instance variables

This little program just doesn't do what I think it should and I cannot understand what the problem is.

I'm running Python 2.4 on Windoze XP.

It contains an album class, an album collection class, a track class, and a track collection class.

It seems confused about which instance is which -- when it says Albums.Tracks.Count() the two instances are unique, but when it says Album.Tracks you get both instances combined. It's as if all accessors in Python are equal, but some accessors are more equal than others :-)

Here's the code. It is the smallest example I could make to demonstrate this behavior.
Expand|Select|Wrap|Line Numbers
  1. # Making a nested set of objects
  2. # A track
  3. class TrackClass:
  4.     def __init__(self, ID, Title):
  5.         self.ID        = ID
  6.         self.Title     = Title
  7.  
  8. # A collection of Tracks
  9. class TracksClass:
  10.     Items      = []
  11.     ItemCount  = 0
  12.     def Add(self, ID, Title):
  13.         self.Items.append(TrackClass(ID,Title))
  14.         self.ItemCount += 1
  15.     def Count(self): return self.ItemCount
  16.     def __getitem__(self,ordinal): return self.Items[ordinal]
  17.  
  18. class AlbumClass:
  19.     def __init__(self,ID,Title):
  20.         self.ID       = ID
  21.         self.Title    = Title
  22.         self.Tracks   = TracksClass()
  23. # A collection of Albums
  24. class AlbumsClass:
  25.     Items      = []
  26.     ItemCount  = 0
  27.     def Add(self,ID,Title):
  28.         self.Items.append(AlbumClass(ID,Title))
  29.         self.ItemCount += 1
  30.     def __getitem__(self,ordinal): return self.Items[ordinal]
  31.     def Count(self)  : return self.ItemCount
  32.  
  33.  
  34. Albums = AlbumsClass()
  35. Albums.Add(ID = 1, Title = "First Album")
  36. Albums[0].Tracks.Add(ID = 1, Title = "First Album First Track")
  37. Albums[0].Tracks.Add(ID = 2, Title = "First Album Second Track")
  38. Albums.Add(ID = 2, Title = "Second Album")
  39. Albums[1].Tracks.Add(ID = 3, Title = "Second Album First Track")
  40. Albums[1].Tracks.Add(ID = 4, Title = "Second Album Second Track")
  41. Albums[1].Tracks.Add(ID = 5, Title = "Second Album Third Track")
  42.  
  43. print "This does not print the expected results"
  44. for Album in Albums:
  45.     print "Album (%i) %s has %i tracks" % (Album.ID, Album.Title, Album.Tracks.Count())
  46.     for Track in Album.Tracks:
  47.         print "     Track: (%i) %s" % (Track.ID, Track.Title)
  48.     print ""
Sep 26 '07 #1
6 2699
bvdet
2,851 Expert Mod 2GB
This little program just doesn't do what I think it should and I cannot understand what the problem is.

I'm running Python 2.4 on Windoze XP.

It contains an album class, an album collection class, a track class, and a track collection class.

It seems confused about which instance is which -- when it says Albums.Tracks.Count() the two instances are unique, but when it says Album.Tracks you get both instances combined. It's as if all accessors in Python are equal, but some accessors are more equal than others :-)

Here's the code. It is the smallest example I could make to demonstrate this behavior.
Expand|Select|Wrap|Line Numbers
  1. # Making a nested set of objects
  2. # A track
  3. class TrackClass:
  4.     def __init__(self, ID, Title):
  5.         self.ID        = ID
  6.         self.Title     = Title
  7.  
  8. # A collection of Tracks
  9. class TracksClass:
  10.     Items      = []
  11.     ItemCount  = 0
  12.     def Add(self, ID, Title):
  13.         self.Items.append(TrackClass(ID,Title))
  14.         self.ItemCount += 1
  15.     def Count(self): return self.ItemCount
  16.     def __getitem__(self,ordinal): return self.Items[ordinal]
  17.  
  18. class AlbumClass:
  19.     def __init__(self,ID,Title):
  20.         self.ID       = ID
  21.         self.Title    = Title
  22.         self.Tracks   = TracksClass()
  23. # A collection of Albums
  24. class AlbumsClass:
  25.     Items      = []
  26.     ItemCount  = 0
  27.     def Add(self,ID,Title):
  28.         self.Items.append(AlbumClass(ID,Title))
  29.         self.ItemCount += 1
  30.     def __getitem__(self,ordinal): return self.Items[ordinal]
  31.     def Count(self)  : return self.ItemCount
  32.  
  33.  
  34. Albums = AlbumsClass()
  35. Albums.Add(ID = 1, Title = "First Album")
  36. Albums[0].Tracks.Add(ID = 1, Title = "First Album First Track")
  37. Albums[0].Tracks.Add(ID = 2, Title = "First Album Second Track")
  38. Albums.Add(ID = 2, Title = "Second Album")
  39. Albums[1].Tracks.Add(ID = 3, Title = "Second Album First Track")
  40. Albums[1].Tracks.Add(ID = 4, Title = "Second Album Second Track")
  41. Albums[1].Tracks.Add(ID = 5, Title = "Second Album Third Track")
  42.  
Expand|Select|Wrap|Line Numbers
  1. print "This does not print the expected results"
  2. for Album in Albums:
  3.     print "Album (%i) %s has %i tracks" % (Album.ID, Album.Title, Album.Tracks.Count())
  4.     for Track in Album.Tracks:
  5.         print "     Track: (%i) %s" % (Track.ID, Track.Title)
  6.     print ""
I added code tags for you. Now we can see your code structure.
Sep 27 '07 #2
Well, this looks like a BUG to me -- if someone with a newer version (I'm on 2.4) would run this and let me know what the results are I'd appreciate it.

The MooseMiester
Sep 28 '07 #3
bvdet
2,851 Expert Mod 2GB
Well, this looks like a BUG to me -- if someone with a newer version (I'm on 2.4) would run this and let me know what the results are I'd appreciate it.

The MooseMiester
I see no bug. You need an __init__ method in TracksClass to create an instance. The tracks are accumulating as a class attribute.
Sep 28 '07 #4
bartonc
6,596 Expert 4TB
Here's the deal. When you declare class variables as in:
Expand|Select|Wrap|Line Numbers
  1. # A collection of Tracks
  2. class TracksClass:
  3.     Items      = []
  4.     ItemCount  = 0
you create variables shared by all instances.

Instance variables are always assigned as
Expand|Select|Wrap|Line Numbers
  1. self.something = value
Preferably, but not necessarily, in __init__().
Sep 28 '07 #5
Thanks bartonc

I would not have guessed that it worked this way in a hundred years, as I expect something called a "class" to exhibit a degree of "encapsulation" without me having to explicitly make that happen -- Silly me!!

What IDE are you using? Coming from C++ C# what's missing the most in Python is a good IDE, like Visual Studio from MickeySoft.

Thanks Again

The MooseMiester
Oct 1 '07 #6
bartonc
6,596 Expert 4TB
Thanks bartonc

I would not have guessed that it worked this way in a hundred years, as I expect something called a "class" to exhibit a degree of "encapsulation" without me having to explicitly make that happen -- Silly me!!
I have to disagree with you, here. This is an ideal implementation of the object model: Just as two (or more) objects in the real world may share resources, so, too, may instances of Python objects. Consider two debit cards on an account : Each has its own PIN (instance variable), but using one to withdraw money will effect the balance available to the other.
What IDE are you using? Coming from C++ C# what's missing the most in Python is a good IDE, like Visual Studio from MickeySoft.

Thanks Again

The MooseMiester
I use Boa Constructor. I find it flexible and stable. And it's free. For other options, check out this review.
Oct 1 '07 #7

Sign in to post your reply or Sign up for a free account.

Similar topics

3
by: David MacQuigg | last post by:
I am writing a chapter for teaching OOP in Python. This chapter is intended as a brief introduction to replace the more complete discussion in Learning Python, 2nd ed, pp. 295-390. I need to...
2
by: Kenneth McDonald | last post by:
I've recently used subclasses of the builtin str class to good effect. However, I've been unable to do the following: 1) Call the constructor with a number of arguments other than the number of...
15
by: Mon | last post by:
I am in the process of reorganizing my code and came across and I came across a problem, as described in the subject line of this posting. I have many classes that have instances of other classes...
0
by: JackRazz | last post by:
Is it possible to serialize a static class containing shared variables like I can serialize an instance of a normal class (obj)? I had a static class, but I gave up and converted it into a normal...
14
by: Jordan Marr | last post by:
I have the following class: class ProvisionCollection { ... private int m_VarianceCount; public int VarianceCount { get { return m_VarianceCount; }
7
by: JonathanB | last post by:
Ok, I know there has to be a way to do this, but my google-fu fails me (once more). I have a class with instance variables (or should they be called attributes, I'm newish to programming and get...
2
by: inadsad | last post by:
Good Day Group, Recently I started a small test project in C# VS 05 for learning purposes. I have a class and a form. I defined a property in a class with get/set and create an instance of...
2
by: Nikolaus Rath | last post by:
Hello, I am really surprised that I am asking this question on the mailing list, but I really couldn't find it on python.org/doc. Why is there no proper way to protect an instance variable...
0
by: Joe Strout | last post by:
On Nov 10, 2008, at 2:44 PM, Zane Selvans wrote: How are you creating your list? You need to make sure that each instance creates its very own list object, something like: self.foo = ...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.