What is the difference between old style and new style classes in Python? When should I use one or the other?
8 Answers
From New-style and classic classes:
Up to Python 2.1, old-style classes were the only flavour available to the user.
The concept of (old-style) class is unrelated to the concept of type: if
xis an instance of an old-style class, thenx.__class__designates the class ofx, buttype(x)is always<type 'instance'>.This reflects the fact that all old-style instances, independently of their class, are implemented with a single built-in type, called instance.
New-style classes were introduced in Python 2.2 to unify the concepts of class and type. A new-style class is simply a user-defined type, no more, no less.
If x is an instance of a new-style class, then
type(x)is typically the same asx.__class__(although this is not guaranteed – a new-style class instance is permitted to override the value returned forx.__class__).The major motivation for introducing new-style classes is to provide a unified object model with a full meta-model.
It also has a number of immediate benefits, like the ability to subclass most built-in types, or the introduction of "descriptors", which enable computed properties.
For compatibility reasons, classes are still old-style by default.
New-style classes are created by specifying another new-style class (i.e. a type) as a parent class, or the "top-level type" object if no other parent is needed.
The behaviour of new-style classes differs from that of old-style classes in a number of important details in addition to what type returns.
Some of these changes are fundamental to the new object model, like the way special methods are invoked. Others are "fixes" that could not be implemented before for compatibility concerns, like the method resolution order in case of multiple inheritance.
Python 3 only has new-style classes.
No matter if you subclass from
objector not, classes are new-style in Python 3.
13 Comments
type(x). If I'm not subclassing a built in type, then there doesn't seem to be any advantage that I can see of the new-style classes. There is a disadvantage, which is the extra typing of (object).super() don't work on old-style classes. Not to mention, as that article says, there are fundamental fixes, like MRO, and special methods, which is more than a good reason to use it.Declaration-wise:
New-style classes inherit from object, or from another new-style class.
class NewStyleClass(object): pass class AnotherNewStyleClass(NewStyleClass): pass Old-style classes don't.
class OldStyleClass(): pass Python 3 Note:
Python 3 doesn't support old style classes, so either form noted above results in a new-style class.
6 Comments
object.class AnotherOldStyleClass: passclass A: pass and class A(): pass are strictly equivalent. The first means "A doesn't inherit of any parent class" and the second means "A inherits of no parent class" . That's quite similar to not is and is notImportant behavior changes between old and new style classes
- super added
- MRO changed (explained below)
- descriptors added
- new style class objects cannot be raised unless derived from
Exception(example below) __slots__added
MRO (Method Resolution Order) changed
It was mentioned in other answers, but here goes a concrete example of the difference between classic MRO and C3 MRO (used in new style classes).
The question is the order in which attributes (which include methods and member variables) are searched for in multiple inheritance.
Classic classes do a depth-first search from left to right. Stop on the first match. They do not have the __mro__ attribute.
class C: i = 0 class C1(C): pass class C2(C): i = 2 class C12(C1, C2): pass class C21(C2, C1): pass assert C12().i == 0 assert C21().i == 2 try: C12.__mro__ except AttributeError: pass else: assert False New-style classes MRO is more complicated to synthesize in a single English sentence. It is explained in detail here. One of its properties is that a base class is only searched for once all its derived classes have been. They have the __mro__ attribute which shows the search order.
class C(object): i = 0 class C1(C): pass class C2(C): i = 2 class C12(C1, C2): pass class C21(C2, C1): pass assert C12().i == 2 assert C21().i == 2 assert C12.__mro__ == (C12, C1, C2, C, object) assert C21.__mro__ == (C21, C2, C1, C, object) New style class objects cannot be raised unless derived from Exception
Around Python 2.5 many classes could be raised, and around Python 2.6 this was removed. On Python 2.7.3:
# OK, old: class Old: pass try: raise Old() except Old: pass else: assert False # TypeError, new not derived from `Exception`. class New(object): pass try: raise New() except TypeError: pass else: assert False # OK, derived from `Exception`. class New(Exception): pass try: raise New() except New: pass else: assert False # `'str'` is a new style object, so you can't raise it: try: raise 'str' except TypeError: pass else: assert False 1 Comment
Old style classes are still marginally faster for attribute lookup. This is not usually important, but it may be useful in performance-sensitive Python 2.x code:
In [3]: class A: ...: def __init__(self): ...: self.a = 'hi there' ...: In [4]: class B(object): ...: def __init__(self): ...: self.a = 'hi there' ...: In [6]: aobj = A() In [7]: bobj = B() In [8]: %timeit aobj.a 10000000 loops, best of 3: 78.7 ns per loop In [10]: %timeit bobj.a 10000000 loops, best of 3: 86.9 ns per loop
6 Comments
%timeit aobj.a 10000000 loops, best of 3: 66.1 ns per loop %timeit bobj.a 10000000 loops, best of 3: 53.9 ns per loopGuido has written The Inside Story on New-Style Classes, a really great article about new-style and old-style class in Python.
Python 3 has only new-style class. Even if you write an 'old-style class', it is implicitly derived from object.
New-style classes have some advanced features lacking in old-style classes, such as super, the new C3 mro, some magical methods, etc.
Comments
Here's a very practical, true/false difference. The only difference between the two versions of the following code is that in the second version Person inherits from object. Other than that, the two versions are identical, but with different results:
Old-style classes
class Person(): _names_cache = {} def __init__(self,name): self.name = name def __new__(cls,name): return cls._names_cache.setdefault(name,object.__new__(cls,name)) ahmed1 = Person("Ahmed") ahmed2 = Person("Ahmed") print ahmed1 is ahmed2 print ahmed1 print ahmed2 >>> False <__main__.Person instance at 0xb74acf8c> <__main__.Person instance at 0xb74ac6cc> >>>New-style classes
class Person(object): _names_cache = {} def __init__(self,name): self.name = name def __new__(cls,name): return cls._names_cache.setdefault(name,object.__new__(cls,name)) ahmed1 = Person("Ahmed") ahmed2 = Person("Ahmed") print ahmed2 is ahmed1 print ahmed1 print ahmed2 >>> True <__main__.Person object at 0xb74ac66c> <__main__.Person object at 0xb74ac66c> >>>
5 Comments
_names_cache is a dictionary that caches (stores for future retrieval) every name you pass to Person.__new__. The setdefault method (defined in any dictionary) takes two arguments : a key and a value. If the key is in the dict, it will return its value. If it's not in the dict, it will set it first to the value passed as second argument and then return it.__new__() is always called, and it always constructs a new object, and then throws it. In this case a if is preferable over .setdefault().__new__ isn't actually a thing for old-style classes, it doesn't get used in instance construction (it's just a random name that looks special, like defining __spam__). So constructing the old-style class only invokes __init__, while the new-style construction invokes __new__ (coalescing to singleton instance by name) to construct, and __init__ to initialize it.New-style classes inherit from object and must be written as such in Python 2.2 onwards (i.e. class Classname(object): instead of class Classname:). The core change is to unify types and classes, and the nice side-effect of this is that it allows you to inherit from built-in types.
Read descrintro for more details.
Comments
New style classes may use super(Foo, self) where Foo is a class and self is the instance.
super(type[, object-or-type])Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.
And in Python 3.x you can simply use super() inside a class without any parameters.