October 27, 2009, 6:54 pm
In the world of computer languages, nothing speaks louder than who adopts its usage. The Python language hit a home run with Google adopting it for a high percentage of their internal and public (Google App Engine) projects. One of the things that makes the Python language appealing to so many is how it treats everything as an object. This makes the language inherently object-oriented but not so complex and wordy that it can‚Äôt be understood by beginning programmers.
This article will give an overview of the basic object-oriented concepts in Python. We‚Äôll start by defining an object and learning what it is. Next, we‚Äôll take a look at how you can discover the properties of Python's built-in objects and how you can create your own. Then we‚Äôll finish off with a list of best practices and a pointer to where you can go to get more information.
The Python language is growing in acceptance and has made itself useful for a variety of purposes and platforms, everything from mobile phones to major websites to windowed applications and more. With so many ways to employ the language, a standardized method for sharing functionality in an extensible fashion is imperative. Fortunately, Python has provided the solution to its own problem in the form of objects.
An object is an entity defined by a class containing attributes and methods which can be inherited and can also inherit functionality from others in a variety of scopes. Objects simplify writing reusable code, thereby making the development process faster and more efficient. Objects are not unique to the Python language, but there certainly are some unique aspects. For instance, Python uses underscores in attribute names to mark accessibility rather than taking the traditional method of using keywords, thereby decreasing the amount of code needed. Note the contrast between Python and Java shown below.
When delivering software libraries, a developer needs to have a standardized way to allow for others to extend and integrate the functionality they are providing. Using objects and inheritance, this is made simple.
Here is some of the syntax for Python.
A class defines the behavior and attributes of an object. It is the blueprint, if you will, for an object. Note that Python uses the # symbol to denote comments, so those lines are not executable parts of the program. The basic syntax looks like this:
The first line is the class keyword followed by the name of the class, any parent classes (more on that later), a colon, and a code block containing the body of the class. (pass is just a place-holding keyword)
An attribute is created by a variable assignment within the scope of the class body as in this example:
This creates an attribute name whose value is a string John Doe. Now we can access the attribute as if it were a variable by combining the object and attribute names with a dot in the following manner:
Classes vs. Instances
A class and an instance are two different but related things. A class is a type while an instance is a single occurrence of some class. To create an instance (also known as "instantiating a class") call the class as if it were a function including any arguments to pass to the constructor (more on that later):
Now we have an instance of the Person class called my_instance. As you can see, it shares much the same initial state as the class itself, but just a little experimentation will show that they are now separate and distinct entities.
This part assumes you know how to declare a function, but in the event you do not you can copy the examples shown here.
A method is to a function what an attribute is to a variable. That is, they are the same except that one is defined as the child of a class/object. A method is simply a function defined within the scope of a class or, more appropriately, a callable attribute. Take this example:
This basic instance method simply prints out the name of that Person. The self argument is automatically supplied when the method is called and is a reference to this particular instance:
Here we instantiated the Person class, used the print_name method, changed the name attribute, and called the method again with the new value.
It can Inherit Functionality
Python uses base classes, or super classes, to allow developers to take advantage of library functionality. A super class is a class that defines attributes and methods that can then be inherited by other classes. Let's say we want to make another type of Person called a Plumber, and we want to change the name attribute. We could reuse our existing class to avoid repetition and speed up the development process:
With a single word we've inherited whatever functionality may be found in the base class. We then replace or override the attribute with these results:
Now we can extend and customize existing objects however we need to. What if we want to combine functionality from two or more base classes? ¬†Here‚Äôs an example:
We've added a base class that defines another attribute, gender, and changed the Plumber class to inherit from both Person and Man. If we play around with our new Plumber class, we can see that the attributes and methods of the two classes have now been merged.
Now that we've covered instantiation, methods, and inheritance, let's see how they overlap. You probably noticed from the first class example that basic classes inherit from object. This is a Python base class that provides a standardized control mechanism for objects. All of your classes should trace back to object. One of the methods the object class provides is the constructor or __init__ method. When you instantiate a class, the arguments passed to the call are directed to the constructor which is always run at instantiation. Let's add a constructor to our Person class to make things a little more dynamic:
So now when we instantiate a person we can pass in the name to the constructor rather than having to assign the attribute later. We also provided a default value for the argument in case the user leaves it empty. You'll notice we're calling the parent constructor. Backward compatibility is maintained since the constructor will run in the same way with no arguments as seen in this example:
What to Do With Conflicting Attributes
If you frequently use multiple inheritance you may have to take a little more time to merge two classes into one. The first listed class takes precedence over any others and overrides any other parent classes. Here's an example of conflicting methods:
Now we've modified the Man class to have its own print_name method to add the prefix to the hard-coded name.¬† In addition, we‚Äôve removed the attribute definition in the Plumber class since that's now supplied via the Person constructor. At this point we have a problem if we wanted to use that nifty new print_name method with the Plumber class since Person.print_name takes precedence over Man.print_name as seen in the following example.
So we can just do this, right?
Wrong! This will raise an exception since the constructor for Man is overriding the constructor for Person which takes an argument. We need to take just the constructor from the Person class and let the Man class override everything else. Here's how to do it:
So all we did here is write our own constructor using wildcards to catch all positional arguments (those passed in without a name associated with them) and keyword arguments as args and kwargs to pass on to the Person constructor. Obviously, the Man constructor takes no arguments.
Objects are an easy and efficient way to expose your code for others to use and to combine different features to build the ultimate programming experience. You should use them when possible in your programming to allow for reuse at later times. Be sure to document and test your code!