What is the difference between old style and new style classes in Python? When should I use one or the other?
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, 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
object
or not, classes are new-style in Python 3.
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 class MyClass
? Or do I still need to do class MyClass(object)
? –
Delorisdelorme object
even in Python 3 where old-style classes is gone. –
Gocart 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 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 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.
object
. –
Thrum class AnotherOldStyleClass: pass
–
Seleneselenious 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 not
–
Jurywoman class OldStyleOptional(object): pass
–
Mastin 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
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
%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 loop
–
Sanctity 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.
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> >>>
_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 __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 __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 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.
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.
© 2022 - 2024 — McMap. All rights reserved.
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