What is the difference between old style and new style classes in Python?
Asked Answered
S

8

1129

What is the difference between old style and new style classes in Python? When should I use one or the other?

Sugihara answered 10/9, 2008 at 18:1 Comment(0)
C
624

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 x is an instance of an old-style class, then x.__class__ designates the class of x, but type(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 as x.__class__ (although this is not guaranteed – a new-style class instance is permitted to override the value returned for x.__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 object or not, classes are new-style in Python 3.

Chirpy answered 10/9, 2008 at 18:1 Comment(13)
None of these differences sound like compelling reasons to use new-style classes, yet everyone says you should always use the new-style. If I'm using duck typing like I should, I never need to use 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).Ritualize
Certain features like 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.Topotype
Do I still need to worry about this new-style old-style distinction in 2012 with python 2.7? The documentation doesn't say anything about them. Can I just declare classes as class MyClass? Or do I still need to do class MyClass(object)?Delorisdelorme
@User: You should still use new-style classes, in Python 2.7, yes. It is recommended to explicitly subclass from object even in Python 3 where old-style classes is gone.Gocart
@User: Old-style classes behave the same in 2.7 as they did in 2.1—and, because few people even remember the quirks, and the documentation no longer discusses most of them, they're even worse. The documentation quote above directly says this: there are "fixes" that could not be implemented on old-style classes. Unless you want to run into quirks that nobody else has dealt with since Python 2.1, and that the documentation no longer even explains, don't use old-style classes.Butter
Here's an example of a quirk you may stumble upon if you use old-style classes in 2.7: bugs.python.org/issue21785Knossos
For anyone wondering, a good reason to explicitly inherit from object in Python 3 is that it makes support multiple versions of Python easier.Czarism
Showing the syntax would help.Ponceau
Metaclasses are new-style only, are they not?Flanker
Another thing that happened about the same time: many builtins e.g. float, int, str, file, used to be built-in functions that returned objects of the appropriate type. They are now type objects - the types existed before, without names; but those types now have 'constructor' behaviour so can replace the functions. I.e. calling the 'float' type converts something to float, etc. You can now say if type(x) is float whereas in older versions you needed e.g. if type(x) is type(1.0). In fact `type' is one of these things which used to be a function and is now a type.Extortioner
"...in Python 3. It is however recommended that you still subclass from object." is no longer correct advice: docs.python.org/2/reference/…Chronology
Plenty of reasons here to use new-style classes only. It makes things easier all around -- keeps the language conceptually simple, reduces confusion, adds functionality, avoids quirks with old-style classes, and ensures compatibility with Python 3.Ryder
@JLPeyret: Yes, but that's not a real concern, since by using a metaclass at all, you're automatically new-style (even if you don't inherit from object). In fact, the Py2 workaround to make all classes in a module new-style by default without inheriting from object is to define __metaclass__ = type at the top of the file, after which all class definitions are implicitly new-style.Hyacinthie
K
339

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.

Katiakatie answered 30/7, 2009 at 1:21 Comment(6)
if a new-style class inherits from another new-style class, then by extension, it inherits from object.Thrum
Is this an incorrect example of old style python class? class AnotherOldStyleClass: passSeleneselenious
@abc I believe that class 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 notJurywoman
Just as a side note, for 3.X, the inheritance of "object" is automatically assumed (meaning that we've got no way to not inherit "object" in 3.X). For the backward compatibility reason, it is not bad to keep "(object)" there though.Ablepsia
If we're going to get technical about inherited classes, this answer should note that you an create another old-style class by inheriting from an old style class. (As written, this answer leaves the user questioning whether you can inherit from an old-style class. You can.)Czarism
Old style classes can also (optionally) inherit from object, or from another class. class OldStyleOptional(object): passMastin
C
246

Important 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
Chubby answered 13/11, 2013 at 9:36 Comment(1)
Nice clear summary, thanks. When you say "difficult to explain in English" I think you are describing a postorder depth-first search as opposed to the old-style class which uses a preorder depth-first search. (preorder means we search ourself before our first child and postorder means we search ourself after our last child).Gisborne
C
41

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
Creon answered 12/7, 2010 at 11:26 Comment(6)
Interesting that you noticed in practice, I just read that this is because new-style classes, once they have found the attribute in the instance dict, have to do an additional lookup to work out whether it is a description, ie, it has a get method that needs to be invoked to get the value to be returned. Old style classes simple return the found object with no addition computations (but then do not support descriptors). You can read more in this excellent post by Guido python-history.blogspot.co.uk/2010/06/…, specifically the section on slotsMillett
doesn’t seem to be true with CPython 2.7.2: %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 loopSanctity
Still faster for aobj in CPython 2.7.2 on x86-64 Linux for me.Creon
It's probably a bad idea to rely on pure Python code for performance sensitive applications. Nobody says: "I need fast code so I'll use old-style Python classes." Numpy doesn't count as pure Python.Automatism
also in IPython 2.7.6, this isn't true. ''''477 ns vs. 456 ns per loop''''Societal
In IPython 2.7.6 I still find it true, 32.4 vs 39ns (i7-2760QM, Linux, x86-64)Creon
T
40

Guido 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.

Tepefy answered 24/4, 2013 at 13:41 Comment(0)
U
26

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:

  1. 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>
    >>>
    
    
  2. 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>
    >>>
    
Univalence answered 9/10, 2013 at 13:40 Comment(5)
what does '_names_cache' do? Could you share a reference?Nonjuror
_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.Univalence
The usage is wrong. The idea is to not construct a new object if it already exists, but in your case __new__() is always called, and it always constructs a new object, and then throws it. In this case a if is preferable over .setdefault().Abscission
But, I didn't get why is the difference in the output i.e. in old style class the two instances were different thus returned False, but in new style class, both the instances are same. How ? What is the change in new style class, that made the two instances same, which was not in old style class ?Biaxial
@PabitraPati: It's kind of a cheap demonstration here. __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.Hyacinthie
D
10

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.

Deshawndesi answered 28/10, 2008 at 9:54 Comment(0)
S
8

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.

Shafting answered 30/4, 2013 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.