Untitled-2

Object Oriented Programming for Beginners



For many Python programmers, object oriented programming is a frightening concept, full of complicated syntax and other roadblocks. Object Oriented Programming (OOP) is a very powerful way of organizing your code, and a solid understanding of the concepts behind it can really help you get the most out of your coding.

Understanding Object-Oriented Programming

Object-oriented programming is a style of coding that allows developers to group similar tasks into classes. This helps keep code following the tenet “don’t repeat yourself” (DRY) and easy-to-maintain.

One of the major benefits of DRY programming is that, if a piece of information changes in your program, usually only one change is required to update the code. One of the biggest nightmares for developers is maintaining code where data is declared over and over again, meaning any changes to the program become an infinitely more frustrating game of Where’s Waldo? as they hunt for duplicated data and functionality.

OOP is intimidating to a lot of developers because it introduces new syntax and, at a glance, appears to be far more complex than simple procedural, or inline, code. However, upon closer inspection, OOP is actually a very straightforward and ultimately simpler approach to programming.

Understanding Objects and Classes

Before you can get too deep into the finer points of OOP, a basic understanding of the differences between objects and classes is necessary. This section will go over the building blocks of classes, their different capabilities, and some of their uses.

Recognizing the Differences Between Objects and Classes

object oriented programming

Right off the bat, there’s confusion in OOP: seasoned developers start talking about objects and classes, and they appear to be interchangeable terms. This is not the case, however, though the difference can be tough to wrap your head around at first.

A class, for example, is like a blueprint for a car. It defines the shape of the car on paper, with relationships between the different parts of the car clearly defined and planned out, even though the car doesn’t exist.

An object, then, is like the actual car built according to that blueprint. The data stored in the object is like the tyres, wires, and engine that compose the car: without being assembled according to the blueprint, it’s just a pile of stuff. However, when it all comes together, it becomes an organized, useful car.

The primary difference between classes and instances or objects is that classes are a kind of factory for generating instances. For example, in a realistic application, we might have an
Employee class that defines what it means to be an employee; from that class, we generate
actual Employee instances. This is another difference between classes and modules: we
only ever have one instance of a given module in memory (that’s why we have to reload
a module to get its new code), but with classes, we can make as many instances as we
need.

Classes form the structure of data and actions and use that information to build objects. More than one object can be built from the same class at the same time, each one independent of the others. Continuing with our construction analogy, it’s similar to the way an entire subdivision can be built from the same blueprint: 150 different cars that all look the same but have different components and decorations inside.

Structuring Classes

To define a class, in typical simple Python fashion, we use the word class followed by the name of your new class, a set of braces and colon after the class name.

After creating the class, a new class can be instantiated and stored in a variable like this:

To see the contents of the class, use print()

Try out this process by putting all the preceding code in a new file called test.py in testing folder:

Run the script and the following should display:

In its simplest form, you’ve just completed your first OOP script.

Defining Class Properties

To add data to a class, properties, or class-specific variables, are used. These work exactly like regular variables, except they’re bound to the object and therefore can only be accessed using the object.

To add a property to MyClass, add the following code to your script:

To read this property and output it to the console, reference the object from which to read and the property to be read:

Because multiple instances of a class can exist, if the individual object is not referenced, the script would be unable to determine which object to read from. The use of the dot(.) is an OOP construct that accesses the contained properties and methods of a given object.

Defining Class Methods

Methods are class-specific functions. Individual actions that an object will be able to perform are defined within the class as methods.

For instance, to create methods that would set and get the value of the class property prop1, add the following to your code:

To use these methods, call them just like regular functions, but first, reference the object they belong to. 
Note
 — OOP allows objects to reference themselves using self.
When you are calling an instance method, by default the current object is passed as the first parameter to the function. In our case if we leave out the self and write the above example like this:

Running this script will get you an error:

The reason is, when you call setProperty like this:

it will be actually treated like this:

The reason why the current object is passed is, to let the instance method make changes to the object. (Remember Python doesn’t have any other keyword like this, like in some other languages).

But our function’s signature doesn’t match this (it expects only one parameter). That’s why it is throwing an error.

To fix this, you have to change the signature to something like this

The self parameter will receive the current object being passed.

Now, read the property from MyClass, change its value, and read it out again by making the modifications below:

Run the script and you’ll see the following:

The power of OOP becomes apparent when using multiple instances of the same class.

Running this script will load the results in your console, they read as follows:

As you can see, OOP keeps objects as separate entities, which makes for easy separation of different pieces of code into small, related bundles.

Magic Methods in OOP

To make the use of objects easier, Python also provides a number of magic methods, or special methods that are called when certain common actions occur within objects. This allows developers to perform a number of useful tasks with relative ease.

Using Constructors and Destructors

When an object is instantiated, it’s often desirable to set a few things right off the bat. To handle this, Python provides the magic method __init__(), which is called automatically whenever a new object is created.

For the purpose of illustrating the concept of constructors, add a constructor to MyClass that will output a message whenever a new instance of the class is created:

To call a function when the object is destroyed, the __del__() magic method is available. This is useful for class cleanup (closing a database connection, for instance).

Output a message when the object is destroyed by defining the magic method
__del__() in MyClass:

When the end of a file is reached, Python automatically releases all resources.

To explicitly trigger the destructor, you can destroy the object using the function del():

Tip — In addition to the magic methods discussed in this section, several others are available. For a complete list of magic methods, see the Python manual page.

Using Class Inheritance

Classes can inherit the methods and properties of another class. For instance, to create a second class that extends MyClass and adds a method, you would add the following to your test file:

Overwriting Inherited Properties and Methods

To change the behavior of an existing property or method in the new class, you can simply overwrite it by declaring it again in the new class:

Assigning the Visibility of Properties and Methods

A lot of folks learn object-oriented programming with languages like C++ and Java. And while they learn, they’re told repeatedly (over and over again), that encapsulation is one of the key principles of object-oriented paradigm and that they should take advantage of it. Sure, until you get down with Python.

In C++ and Java, things are pretty straight-forward. There are 3 magical and easy to remember access modifiers, that will do the job (public, protected and private). But there’s no such a thing in Python. That might be a little confusing at first, but it’s possible too. We’ll have look at how do it right in Python.

Python doesn’t have any mechanisms, that would effectively restrict you from accessing a variable or calling a member method. All of this is a matter of culture and convention.

Public properties and methods

All member variables and methods are public by default in Python. So when you want to make your member public, you just do nothing. All the methods and properties you’ve used so far have been public. This means that they can be accessed anywhere, both within the class and externally.

Protected properties and methods

When a property or method is declared protectedit can only be accessed within the class itself or in descendant classes (classes that extend the class containing the protected method). This feature turns on when on every member name prefixed with at one underscore.

Declare the getProperty() method as protected in MyClass and try to access it directly from outside the class:

Upon attempting to run this script, the following error shows up:

Now, create a new method in MyOtherClass to call the getProperty() method:

Private properties and methods

A property or method declared private is accessible only from within the class that defines it. This means that even if a new class extends the class that defines a private property, that property or method will not be available at all within the child class. This feature turns on when on every member name prefixed with at least two underscores.

To demonstrate this, declare getProperty() as private in MyClass, and attempt to call callProtected() from MyOtherClass:

Call the private functions like this:

These methods are not really private though. When you start a method name with two underscores Python does some name mangling to make it “private” and that’s all it does, it does not enforce anything like other languages do. This explains the “odd” identifier in the error message you got as well. You can find  more about it in the Docs.

Static properties and methods

A method or property declared static can be accessed without first instantiating the class. One of the major benefits to using static properties is that they keep their stored values for the duration of the script.

To demonstrate this, add a property called count and a static method called plusOne() to MyClass. Then set up a while loop to output the incremented value of count as long as the value is less than 10:

Comparing Object-Oriented and Procedural Code

There’s not really a right and wrong way to write code. That being said, this section outlines a strong argument for adopting an object-oriented approach in software development, especially in large applications.

Ease of Implementation

While it may be daunting at first, OOP actually provides an easier approach to dealing with data. Because an object can store data internally, variables don’t need to be passed from function to function to work properly.

Also, because multiple instances of the same class can exist simultaneously, dealing with large data sets is infinitely easier. For instance, imagine you have two people’s information being processed in a file. They need names, occupations, and ages.

1. The Procedural Approach

Here’s the procedural approach to our example:

While this code isn’t necessarily bad, there’s a lot to keep in mind while coding. The dict of the affected person’s attributes must be passed and returned from each function call, which leaves margin for error.

To clean up this example, it would be desirable to leave as few things up to the developer as possible. Only absolutely essential information for the current operation should need to be passed to the functions.

This is where OOP steps in and helps you clean things up.

2. The OOP Approach

Here’s the OOP approach to our example:

There’s a little bit more setup involved to make the approach object oriented, but after the class is defined, creating and modifying people is a breeze; a person’s information does not need to be passed or returned from methods, and only absolutely essential information is passed to each method.

On the small scale, this difference may not seem like much, but as your applications grow in size, OOP will significantly reduce your workload if implemented properly.

Tip — Not everything needs to be object oriented. A quick function that handles something small in one place inside the application does not necessarily need to be wrapped in a class. Use your best judgment when deciding between object-oriented and procedural approaches.

Due to the more compact nature of OOP when done correctly, changes in the code are usually much easier to spot and make than in a long spaghetti code procedural implementation.

If a particular array of information gains a new attribute, a procedural piece of software may require (in a worst-case scenario) that the new attribute be added to each function that uses the array.

An OOP application could potentially be updated as easily adding the new property and then adding the methods that deal with said property.
A lot of the benefits covered in this section are the product of OOP in combination with DRY programming practices. It is definitely possible to create easy-to-maintain procedural code that doesn’t cause nightmares, and it is equally possible to create awful object-oriented code.

Conclusion

At this point, you should feel comfortable with the object-oriented programming style. Learning OOP is a great way to take your programming to that next level. When implemented properly, OOP will help you produce easy-to-read, easy-to-maintain, portable code that will save you (and the developers who work with you) hours of extra work. Are you stuck on something that wasn’t covered in this article? Are you already using OOP and have some tips for beginners? Share them in the comments!
 


  • Cyph0n

    If only there was such a good introduction to Python OOP online when I was trying to wrap my head around it. This will definitely help newcomers though.

  • Bartosz Nowak

    I would like just point that, although it’s very nice introduction to OOP, having setters and getters is not very pythonic. Every setter and getter fuctions only adds execution time for doing simple task of getting reference to data.

  • Kelvin Lomboy

    Wow. Excellent writeup!

  • Humberto Rocha

    Nice introduction but doing just a correction about the public, protected and private thing:

    The one underscore naming doesn’t act like protected. It’s just a naming convention to indicate to other programmers that this is an internal, and shouldn’t be called outside the class.

    The only side effect quoted from PEP-8 is:

    _single_leading_underscore: weak “internal use” indicator. E.g. from M import * does not import objects whose name starts with an underscore.

    In your example the “AttributeError” was raised because you forgot the single underscore on the method call.

  • iDen

    One thing to mention.

    For best practice of real pythonista, strings .format() method should be inside parentheses of print() function. Coz .format() is method of strings, but not print function.

    (Python 3.3.3)
    >>> print(‘{} world’).format(‘Hello’)
    {} world
    Traceback (most recent call last):
    File “”, line 1, in
    print(‘{} world’).format(‘Hello’)
    AttributeError: ‘NoneType’ object has no attribute ‘format’

    >>> print(‘{} world’.format(‘Hello’))
    Hello world

    • Guest

      clever parser adds in the end:
      shouldn’t be there

  • Kirill Zhukov

    Thanks a lot for amazing writeup!

  • nsajeethphilip

    A good introduction. The examples are also to the point. Keep it up.