i don't really understand member variables..

Chermside, Michael mchermside at ingdirect.com
Thu Oct 24 12:50:23 EDT 2002


Actually, you probably DO understand member variables... 
but what you're using is NOT member variables.

When you want a member variable, you do this:
	>>> class Dog:
	... 	def __init__(self, color):
	... 		self.color = color
	... 		
	>>> rover = Dog('Black')

I have created a class (Dog), with a member variable
(color), then created a particular instance of Dog
(which I referred to as "rover"), that has a color
of black.

Member variables are NOT shared -- they're specific
to each instance (or 'member', which is where the
name comes from). So I can create an irish setter:

	>>> rex = Dog('Rust Red')

And they both exist, and have different colors:

	>>> [x.color for x in (rover, rex)]
	['Black', 'Rust Red']

This is that you will use 98% of the time.

In most languages, the SET of member variables is
fixed for a class (although the VALUES can be 
different for different instances). But Python is
more flexible than that. I can give rex a leash:

	>>> rex.leash = 'the stretchy leash'

And doing so doesn't affect rover at all (here's two
different ways to tell):

	>>> dir(rex)
	['__doc__', '__init__', '__module__', 'color', 'leash']
	>>> dir(rover)
	['__doc__', '__init__', '__module__', 'color']
	>>> rex.__dict__
	{'color': 'Rust Red', 'leash': 'the stretchy leash'}
	>>> rover.__dict__
	{'color': 'Black'}

HOWEVER, this ability to add new member variables
to particular instances is NOT something you will do
everyday... for most mundane tasks, you'll set up the
member variables in the __init__ function and then
use them. (In Python 2.2+ there's a way to optimize
the performance of your class if you know you'll never
add new member variables, but that's a bit advanced.)

------------------------------------------

Now, about what YOU were doing. You set a value within
the class DEFINITION, instead of inside the __init__
method of that class. This does something else entirely.
It does not create a member variable, but instead
something which (for lack of a better term) I will call
a "class variable". As you correctly noted, this is
shared amongst all of the instances of the class.

Why would you do this? Well, normally you wouldn't.
Instance variables are much more useful than class
variables, and the latter are really pretty unusual. But
I can create an example that shows what you might use
it for. Let's create a PedigreedDog class:

	>>> class PedigreedDog(Dog):
	... 	def __init__(self, color, breed):
	... 		Dog.__init__(self, color)
	... 		self.breed = breed

This keeps track of the breed for each Dog, but with
pedigreed dogs, we really need a universal system for
tracking ALL dogs of a given breed. So let's try that
class again, with some improvements:

	>>> class PedigreedDog(Dog):
	... 	registry = {}
	... 	def __init__(self, color, breed):
	... 		Dog.__init__(self, color)
	... 		self.breed = breed
	... 		self.registry.setdefault(breed, []).append(self)
	... 		

Don't be intimidated by that last line, it simply treats
self.registry as a dictionary where the values are lists,
and adds self, with the key of breed. 

Now we'll create some PedigreedDogs:

	>>> fifi = PedigreedDog('Gray', 'Poodle')
	>>> foofoo = PedigreedDog('Black', 'Poodle')
	>>> mac = PedigreedDog('Rust Red', 'Irish Setter')

then let's take a look at the registry (using pprint to
print it readably):

	>>> import pprint
	>>> pprint.pprint(PedigreedDog.registry)
	{'Irish Setter': [<__main__.PedigreedDog instance at 0x010C0DC8>],
	 'Poodle': [<__main__.PedigreedDog instance at 0x010C2D28>,
	            <__main__.PedigreedDog instance at 0x010B6568>]}

There... that's an example of the kind of thing you might
use "class variables" for. My main point is that unless
you are doing something odd like this, you'll probably
just want to use instance variables, and they get defined
in the __init__ method (although they can also be added
later).

-- Michael Chermside




More information about the Python-list mailing list