(Part 3 of my dissertation; I hope it's useful for you in particular) Up to now in my discussion, it wasn't usually important to know that everything is a class. You just know that everything has attributes, and that you use the dot notation to get at an attribute. So what if "%x".format() is a class method of the class str, you can just learn "this is how you can format text". But once you learn how to write classes, it starts to all come together.
class MyClass (myParentClass): This line, and all indented lines below it, constitute a class. The defs inside are functions, but they're also methods, with special behavior of the first parameter, called 'self' by convention. So a def might look like: def myMethod(self, arg1): return arg1 * 2 Now, if somebody has an instance of your class, they can call this method like: myinstance.myMethod(42) and the return value will be 84. This is remarkably like the notation we used before inside a module. So a class *could* be used just to encode the namespace. But the power comes when there are attributes on the object, and when self is used to get at those attributes. In that situation, the self can refer to all kinds of data. In a sense you could think of that data as being like the globals of a module, except for one very important thing. There's only one instance of the module, so those globals are shared between everyone. But with an instance, you can have many instances, and each has its own set of attributes. Simplest way to illustrate this is with a MyFile class. There's already a very nice class in the standard library, with a builtin function open() to create a new instance. But we can pretend to write such a class, and see how making it a class is probably better than any other way to code the functionality. And in fact, many people have done something like that, to reference something analogous to a file. When we open a class, some code somewhere has to keep track of the system's file handle, the file position, the mode of operation, any buffers that might be used, etc. Whatever that data is, if it's kept in an instance, then it's possible to open multiple files at the same time, some for writing, some for reading, etc. So how might we go about doing that? class MyFile(object): def __init__(self, filename, mode): self.filename = filename #remember the filename, in case someone wants it self.handle = someOScall(filename, mode) #do whatever it might take to actually open a file self.position = 0 self.opened = True def read(self, size): data = someOScallToRead(self.handle, self.size) #do whatever it takes to read some data self.position += size #probably it's more complicated than this return data Now __init__() is a special method name. It's called implicitly when an object of this class is made. A newly created dummy object of the right type is passed to __init__() as self, and we want to stuff that object with the appropriate attributes (typically a dozen or more). read() is a simple method, although it could be *much* more complex for a real file. It might do buffering, or it might translate characters, or almost anything. But by the time it's called, we know the object's __init__() method has been called, a file is open, the handle initialized, etc. So now the user can create two different objects: file1 = MyFile("firstfile.txt", 12) file2 = MyFile("otherdirectory/secondfile.txt", 49) and can unambiguously read from whichever one she likes. This notion that the attributes of the object carries all its necessary data, and that the user of the class need not know any of the details is the reason one can readily write code in separate modules that knows little about the internals. Just pass the necessary object around, and if the class was done right, it'll be ready to do all the operations defined on it. Hope this helps. It's just barely scratched the surface of what's possible. -- DaveA -- http://mail.python.org/mailman/listinfo/python-list