What is the difference between class Foo(): and class Date(object):

Steve D'Aprano steve+python at pearwood.info
Mon Nov 21 09:13:28 EST 2016


On Mon, 21 Nov 2016 11:15 pm, Veek M wrote:

>>>> class Foo():
> ...  pass
> ...
>>>> class Bar(Foo):
> ...  pass
> ...
>>>> b = Bar()
>>>> type(b)
> <type 'instance'>
[...] 

> What is going on here? Shouldn't x = EuroDate();  type(x) give
> 'instance'?? Why is 'b' an 'instance' and 'x' EuroDate?
> Why isn't 'b' Bar?


It looks like you are running Python 2, and have stumbled across an
annoyance from the earliest days of Python: the "classic", or "old-style",
class.

Before Python 2.2, custom classes and built-in types like int, float, dict
and list were different. You have just discovered one of the ways they were
different: instances of custom classes all had the same type, even if the
class was different:

# Python 2

py> class Dog:
...     pass
...
py> class Cat:
...     pass
...
py> lassie = Dog()
py> garfield = Cat()
py> type(lassie) is type(garfield)
True
py> type(lassie)
<type 'instance'>


This is just the most obvious difference between "classic classes" and
types. Some of the other differences:

- The method resolution order (MRO) is different: the classic class
  MRO is buggy for diamond-shaped multiple inheritance, and special
  dunder methods like __eq__ are resolved slightly differently.

- super, properties, class methods and static methods don't work for
  classic classes.

- The metaclass of classic classes is different:

py> type(Dog)
<type 'classobj'>
py> type(float)
<type 'type'>

- Attribute lookup for classic classes is slightly different; in
  particular, the special __getattribute__ method doesn't work.


In Python 2.2, the built-in types (list, dict, float etc) were unified with
the class mechanism, but for backwards compatibility the old-style classes
had to be left in. So Python had two class mechanisms:

- "New-style classes", or types, inherit from object, or some 
  other built-in type, and support properties, etc.

- "Old-style classes", don't inherit from object, don't support
  properties etc.


So in Python 2, when you write:

    class Foo:

or

    class Foo():


you get an old-style class. But when you inherit from object, you get a
new-style class. Classic classes are an obsolete feature from Python 2.
They are removed in Python 3, and things are much simpler. In Python 3, it
doesn't matter whether you write:

    class Foo:
    class Foo():
    class Foo(object):

the result is the same: a new-style class, or type.

The best thing to do in Python 2 is to always, without exception, write

    class Foo(object):

to define your base classes. That will ensure that property, super,
classmethod, staticmethod, __getattribute__, etc. will all work correctly,
and you will avoid the surprises of classic classes.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list