One of the historical oddities of Python is that there are two different kinds of classes, so-called "classic" or "old-style" classes, and "new-style" classes or types. To understand the reason, we have to go back to the dawn of time and very early Python.
Back in the early Python 1.x days, built-in types like
were completely separate from classes you created with the
keyword. Built-in types were written in C, classes were written in Python, and the two could not be combined. So in Python 1.5, you couldn't inherit from built-in types:
>>> class MyInt(int):
Traceback (innermost last):
File "", line 1, in ?
TypeError: base is not a class object
If you wanted to inherit behaviour from a built-in type, the only way to do so was by using delegation
, a powerful and useful technique that is unfortunately underused today. At the time though, it was the only way to solve the problem of subclassing from built-in types, leading to useful recipes like this one from Alex Martelli
But in Python 2.2, classes were unified with built-in types
. This involved a surprising number of changes to the behaviour of classes, so for backwards-compatibility, both the old and the new behaviour was kept. Rather than introduce a new keyword, Python 2.2 used a simple set of rules:
- If you define a class that doesn't inherit from anything, it is an old-style classic class.
- If your class inherits from another classic class, it too is a classic class.
- But if you inherit from a built-in type (e.g.
list) then it is a new-style class and the new rules apply.
- Since Python supports multiple inheritance, you might inherit from both new-style and old-style classes; in that case, your class will be new-style.
To aid with this, a new built-in type was created,
is the parent type of all new-style classes and types, but not old-style classes. Curiously,
still returns True, even though
doesn't actually inherit from
. At least that is the case in Python 2.4 and above, I haven't tested 2.2 or 2.3.
There are a few technical differences in behaviour between the old- and new-style classes, including:
super only works in new-style classes.
- Likewise for
- Properties appear to work in classic classes, but actually don't. They seem to work so long as you only read from them, but if you assign to a property, the setter method is not called and the property is replaced.
- In general, descriptors of any sort only work with new-style classes.
- New-style classes support
__slots__ as a memory optimization.
- The rules for resolving inheritance of old- and new-style classes are slightly different, with old-style classes' method resolution order being inconsistent under certain circumstances.
- New-style classes optimize operator overloading by skipping dunder methods like
__add__ which are defined on the instance rather than the class.
The complexity of having two kinds of class was always intended to be a temporary measure, and in Python 3, classic classes were finally removed for good. Now, all
classes inherit from
, even if you just write
with no explicit bases.