This Tutorial begins our exploration of the Python class—a coding structure and device used to implement new kinds of objects in Python that support inheritance. Classes are Python’s main object-oriented programming (OOP) tool, so we’ll also look at OOP basics along the way in this part of the Tutorial. OOP offers a different and often more effective way of programming, in which we factor code to minimize redundancy, and write new programs by customizing existing code instead of changing it in place.
In Python, classes are created with a new statement: the class. As you’ll see, the objects defined with classes can look a lot like the built-in types. Classes, though, are designed to create and manage new objects, and support inheritance—a mechanism of code customization and reuse above and beyond anything you have seen so far.
Why to use classes?
In simple terms, classes are just a way to define new sorts of stuff, reflecting real objects in a program’s domain. For example, in typical GUI systems, interfaces are written as collections of widgets—buttons, labels, and so on—which are all drawn when their container is drawn (composition). Moreover, we may be able to write our own custom widgets—buttons with unique fonts, labels with new color schemes, and the like—which are specialized versions of more general interface devices (inheritance).
At its base, the mechanism of OOP in Python is largely just two bits of magic: a special first argument in functions (to receive the subject of a call) and inheritance attribute search (to support programming by customization). Other than this, the model is largely just functions that ultimately process built-in types. While not radically new, though, OOP adds an extra layer of structure that supports better programming than flat procedural models. Along with the functional tools, it represents a major abstraction step above computer hardware that helps us build more sophisticated programs.
The end result is that classes define common, shared data and behavior, and generate instances. Instances reflect concrete application entities, and record per-instance data that may vary per object.
Let’s turn to a real example to show how these ideas work in practice. To begin, let’s define a class named firstclass by running a Python class statement interactively:
class firstclass: def setdata(self, value): self.data = value def display(self): print(self.data)
We’re working interactively here, but typically, such a statement would run when the module file it is coded in is imported. Like functions created with defs, this class won’t even exist until Python reaches and runs this statement.
Like all compound statements, the class starts with a header line that lists the class name, followed by a body of one or more nested and (usually) indented statements. Here, the nested statements are defs; they define functions that implement the behavior the class means to export.
def is really an assignment. Here, it assigns function objects to the names setdata and display in the class statement’s scope, and so generates attributes attached to the class—firstclass.setdata and firstclass.display. In fact, any name assigned at the top level of the class’s nested block becomes an attribute of the class.
Functions inside a class are usually called methods. They’re coded with normal defs, and they support defaults, return values, yield items on request, and so on. But in a method function, the first argument automatically receives an implied instance object when called—the subject of the call. We need to create a couple of instances to see how this works:
x = firstclass() y = firstclass()
By calling the class this way (notice the parentheses), we generate instance objects, which are just namespaces that have access to their classes’ attributes. Properly speaking, at this point, we have three objects: two instances and a class. Really, we have three linked namespaces. In OOP terms, we say that x “is a” firstclass, as is y—they both inherit names attached to the class.
The two instances start out empty but have links back to the class from which they were generated. If we qualify an instance with the name of an attribute that lives in the class object, Python fetches the name from the class by inheritance search:
x.setdata("thecleverprogrammer") y.setdata(1000) x.display() y.display()
That’s it for for today, we will learn more about Object Oriented Programming in the next Chapter.