A "New Class" is the recommended way to create a class in modern Python.

A "Classic Class" or "old-style class" is a class as it existed in Python 2.1 and before. They have been retained for backwards compatibility. This page attempts to list the differences.

The syntax for the two types looks the same; "new-style", "old style", "classic", and variants are just descriptions that various people have used; Python hasn't yet settled on a specific official choice for the terminology.

The minor syntactic difference is that New Style Classes happen to inherit from object.

class Old1:

class Old2(Old1, UserDict): # Assuming UserDict is still old-style


class New1(object):
class New2(New1):
class New3(Old1, New2):
class New4(dict, Old1):  # dict is a newstyle class

Warning: In 2.5, magic names (typically those with a double underscore (DunderAlias) at both ends of the name) may look at the class rather than the instance even for old-style classes. I say this based on some python-dev discussion; I didn't notice how solidly the final decision was made. Later discussion extended it to "next" (despite the lack of underscore) and Guido said not to count on it in either direction. Since magic names are supposed be generally reserved anyhow, normal code should not care.

>>> class NewException(Exception, object):

>>> raise NewException

Traceback (most recent call last):
  File "<pyshell#22>", line 1, in -toplevel-
    raise NewException
TypeError: exceptions must be classes, instances, or strings (deprecated), not type

>>> raise NewException()

Traceback (most recent call last):
  File "<pyshell#23>", line 1, in -toplevel-
    raise NewException()
TypeError: exceptions must be classes, instances, or strings (deprecated), not NewException

Old Style classes search each base class, including the bases of the bases, Left To Right. New Style classes search each base class only once, and the order may slightly different than you would get with an ambiguous Old Style class.

>>> class Old: pass
>>> class O1(Old): pass
>>> class O2(Old): pass
>>> class OD(O1, O2): pass

>>> OD.__mro__
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in -toplevel-
AttributeError: class O has no attribute '__mro__'

OK, but write some methods to figure it out... and the effective MRO is

OD, O1, Old, O2, Old

So that Old is searched before its own derived class O2, then (uselessly) searched again at the end.

>>> class New(object): pass
>>> class N1(New): pass
>>> class N2(New): pass
>>> class ND(N1, N2): pass
>>> ND.__mro__
(<class '__main__.ND'>, <class '__main__.N1'>, <class '__main__.N2'>, <class '__main__.New'>, <type 'object'>)

So New (and its own base, object) is only searched once -- after *all* of its own subclasses have already been searched.

Generally, the New MRO is better, but they aren't the same, and it can be painful to inherit from both types of class in the same derived class.

One time when the older method did work better was mixin classes -- if you assume that methods will always be completely overridden (not just extended), then the old conventions are simpler and cleaner. If you need to combine methods, the old conventions (to explicitly call Base.method(self, args)) required a fragile knowledge of the inheritance hierarchy.


NewClassVsClassicClass (last edited 2014-05-07 22:26:07 by DaleAthanasias)

Unable to edit the page? See the FrontPage for instructions.