Alcott
Alcott

Reputation: 18585

Python's new-style classes' base - `object` and `type`

According to the doc, object is all new-style classes' base class.

And AFAIK, the so-called new-style classes are just ones which can acquire some new fetures by inheriting object, right?

I thought object inherit type or use type as its __metaclass__, but object.__bases__ gives me nothing, so where dose this object come from, and what's relationship bewteen it and type?

Upvotes: 5

Views: 2503

Answers (3)

kindall
kindall

Reputation: 184220

Indeed, the type (i.e., metaclass) of object, a class, is type:

type(object) == type      # True

And since object is the base class, it has no parents of its own, as you'd expect:

object.__bases__ == ()    # True

object doesn't have a __metaclass__ attribute because it doesn't need one: it uses the default metaclass, type.

Now it's a little confusing because type is in fact a subclass of object, which boggles the mind (how can type be derived from object when you need type to construct object?) but this is solved by a little hard-coding at the C level in the Python interpreter.

All this applies only to new-style classes, that is, those derived from object. In Python 3, all classes are new-style, so this applies globally in Python 3.

Upvotes: 5

Eli Bendersky
Eli Bendersky

Reputation: 273616

You may find this and this posts interesting. Here's the diagram from the first:

enter image description here

Upvotes: 2

mac
mac

Reputation: 43051

There are two concepts that could be helpful to keep in mind:

  • everything in python is an object, including classes and metaclasses
  • metaclasses are the constructors of classes, not their ancestors, so they do not appear in __bases__.

That means that object indeed has type as metaclass.

Just as a curiosity, the "paradoxical" part of the story is the type, which being a metaclass is also an object, but can't have itself as metaclass (it would be a bit of chicken-and-egg problem, if you think about it).

The paradox is solved with some C voodoo in the python source code, but I don't know much about it!

EDIT: (some example code)

>>> class MyMeta(type):
...     def __new__(cls, name, bases, dct):
...         return type.__new__(cls, name, bases, dct)
... 
>>> class MyClass(object):
...     __metaclass__ = MyMeta
... 

Now observe that obj inherit from object

>>> obj = MyClass()
>>> MyClass.__bases__
(<type 'object'>,)

As for your question in the comments about dir(obj) doesn't output the __metaclass__ attribute: the reason is that __metaclass__ is an attribute of the class not of its instantiated object. Note in fact that:

>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> MyClass.__metaclass__
<class '__main__.MyMeta'>

If you are interested in deepening your understanding of metaclasses, this is a classic SO question (with a very comprehensive answer, of course!):

What is a metaclass in Python?

HTH!

Upvotes: 3

Related Questions