Don’t Use Objects In Python – Part 1

Everyone knows Python is object oriented. It’s right there on on page 13 of introducing python, it says as much on Wikipedia. You might have even seen classes, objects, inheritance and polymorphism in python yourself. But is Python really object oriented?

Let’s first ask, what actually is an object in python? We’ll see for ourselves, by creating a simple python class:

class Record:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def is_over_eighteen(self):
        return self.age > 18

this is just a simple class that has two member fields, name and age and a single method is_over_eighteen. Let’s also create an instance of this class:

my_record = Record("Stubborn", 207)

In Python member fields and methods are known as attributes. We can lookup the attributes of our record just like in any other standard object oriented language by my_record.name, my_record.age and my_record.is_over_eighteen.

Our object also has other secret attributes that are created automatically. Their names start with a double underscore. The attribute we are interested in is my_record.__dict__. If we evaluate this we will see that it is a dictionary of the instance attributes:

{'name': 'Stubborn', 'age': 207}

What’s interesting is that this isn’t just a representation of the object as a dictionary. In python an object is backed by an actual dictionary, and this is how we access it. When we look up an attribute of an object with the normal notation, for example my_record.age, the python interpreter converts it to a dictionary lookup.

The same is true of methods, the only difference is that methods are attributes of the class. So if we evaluate: Record.__dict__ we get something like:

mappingproxy({'__module__': '__main__', '__init__': <function Record.__init__ at 0x7f3b7feec710>, 'is_over_eighteen': <function Record.is_over_eighteen at 0x7f3b7feec7a0>, '__dict__': <attribute '__dict__' of 'Record' objects>, '__weakref__': <attribute '__weakref__' of 'Record' objects>, '__doc__': None})

We can access our method from this dictionary via:

Record.__dict__["is_over_eighteen"](my_record)

So a Python object is really just a wrapper for two dictionaries. Which begs the question, why use an object at all, rather than a dictionary? The only functionality objects add on top of dictionaries is inheritance (more on why that is bad in a later post) and a little syntactic sugar for calling methods. In fact there is one way in which python objects are strictly worse than dictionaries, they don’t pretty print. If we evaluate print(my_record) we will see:

<__main__.Record object at 0x7f3b8094dd10>

not very helpful. Now there is a way to make objects pretty print. We do this by implementing the __repr__ method in our Record class. This is the method used by print to represent an object as a string. However, dictionaries already have __repr__ defined so they will pretty print automatically.

Fundamentally, if you think you want to define a class in python, consider just using a dictionary instead.

What is Single Inheritance, and Why is it Bad?

In a previous post we talked about how there are two different notions of inheritance, Interface Inheritance and Implementation Inheritance. In this post we’ll be talking primarily about the latter. That means, we’ll be talking about using inheritance to share actual logic among classes.

Let’s say we defined two base classes. The first is DatabaseAccessor:

class DatabaseAccessor {
   protected:
   bool WriteToDatabase(string query) {
   // Implementation here
   }

   string ReadFromDatabase(string query) {
   // Implementation here
   }
}

which encapsulates our logic for reading from and writing to some database. The second is Logger:

class Logger {
   protected:
   void LogWarning(string message) {
   // Implementation here
   }

   void LogError(string message) {
   // Implementation here
   }
}

this encapsulates our logic for logging errors and warnings. Now, suppose also that we are using a language the supports multiple inheritance, such as C++. If we want to define a class that shares functionality with both of these classes, we can subclass both of them at once:

class SomeUsefulClass : private DatabaseAccessor, private Logger {
   // Some useful code goes here
}

So, we have a subclass named SomeUsefulClass that can use both the DatabaseAccessor and Logger functionality, great!

What if we wanted to do the same thing in a language like C# or Java? Well then we’re out of luck, in C# and Java you cannot inherit from more than one base class. This is called single inheritance. How do we achieve the same effect if we are using either of these languages? Well, one solution would be to chain our subclasses together. We would choose which of DatabaseAccessor and Logger is more fundamental and make it the subclass of the other. Suppose we decided that everything has to log, then the Logger class remains the same and DatabaseAccessor becomes:

class DatabaseAccessor : private Logger {
   protected:
   bool WriteToDatabase(string query) {
   // Implementation here
   }

   string ReadFromDatabase(string query) {
   // Implementation here
   }
}

So now we can subclass DatabaseAccessor and get the Logger functionality as well. Although, what if we really did just want the DatabaseAccessor logic, and we didn’t actually need the Logger implementation? Well tough luck. Now everything that inherits from DatabaseAccessor inherits from Logger as well.

This might not seem like much of a problem with something as trivial as Logger, but in big enterprise applications, it can spiral out of control. You end up in a situation where all the basic re-usable code you might need is locked inside a lengthy chain of subclasses. What if you only need something from the bottom ring of this chain? Unfortunately, you have to pick up all of it’s base classes as well. This makes our code unnecessarily complicated and harder to read and understand. If one of those unwanted base classes does all kinds of heavy weight initialisation on construction, then it will have performance implications as well.

One consolation that is often offered is that both languages allow multiple inheritance of interfaces. This doesn’t really help us though. Implementation inheritance and Interface Inheritance are two completely different things. We can’t convert one of DatabaseAccessor or Logger into an interface. The entire reason we want to inherit from them is to get their implementation!

We could also use composition instead of inheritance. In this case we would inherit from one of the classes, and keep a reference to the other. But, in that case, why even use single inheritance at all? Why not just let our classes keep references to a Logger and a DatabaseAccessor? The language designers have struck a bizarre compromise here, we can use inheritance, but only a little bit. If C# and Java are Object Oriented, then they should allow us to use the full features of object orientation, rather than just a flavour.

The good news is that the people behind C#, Microsoft, have realised the error in their ways. They have released two features that ameliorate the problem of single inheritance, Extension Methods and Default Implementations in Interfaces. More on these in future blog posts.

The Two Different Types of Inheritance

If, like me, you started life as a C++ developer, you will be surprised to learn that there are actually two completely different notions of Inheritance. In C++, these two different notions get squashed together, but they’re still there.

Imagine we are defining a base class to represent a financial security. In C++ it might look something like this:

class Security {
   public:
   virtual double GetPrice(double interestRate) = 0;
}

Any class that inherits from this base class has to implement the GetPrice method. Apart form that, they may have nothing else in common.

Now, suppose we are writing a base class that encapsulates our database access logic. Again, in C++, it might look a little like this:

class DatabaseAccessor {
   private:
   bool WriteToDatabase(string query) {
   // Implementation here
   }

   string ReadFromDatabase(string query) {
   // Implementation here
   }
}

These two examples illustrate the two different notions of inheritance, interface inheritance and implementation inheritance.

Interface inheritance, also known as type inheritance, is when we use inheritance to specify a common api across different classes. In our first example, every class that implements the Security class will have a public GetPrice method that takes a double argument and returns a double. There can be lots of different Security subclasses, that all calculate their price differently. But they all share the same interface for this functionality. This is interface inheritance.

Now, let’s look at our second example. Any class that inherits from DatabaseAccessor will have a shared implementation for reading from and writing to databases. We are using inheritance here to make our code easier to maintain and re-use. This is implementation inheritance.

When we write C++ we don’t normally distinguish between these two things. Indeed we can mix them freely. For example, suppose we had another class:

class RateCurve {
public:
   virtual double GetRateAt(time_t date);
   double Discount(double value, time_t date) {
      return value * GetRateAt(date);
   }
}

The method GetRateAt defines an interface as it’s a virtual function with no implementation. The method Discount comes with an implementation that will be shared between subclasses. So whenever we inherit from RateCure we will be using interface and implementation inheritance at the same time!

In a language like C# things are quite different. Interface and Implementation inheritance are handled explicitly and separately. If you would like to share implementation you inherit from a class. If you would like to use a common API you implement an interface. Interfaces are defined like so:

public interface ISecurity {
   public double GetPrice(double rate);
}

An interface cannot contain any fields, and (at least up to C# 8.0) interface methods cannot have implementations. This all means that it is a little bit easier to reason about our code. The disadvantage is that we cannot use both interface and implementation inheritance at the same time.