Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Could you expand on that? I’m not sure what exactly you’re saying, because you’re not using standard or unambiguous terminology. (`type` is a thing, but “class” isn’t a thing, but rather a category of things, a syntactic construct.)

Python 2:

  >>> class OldStyleClass: pass
  >>> isinstance(OldStyleClass, type)
  False

  >>> class NewStyleClass(object): pass
  >>> isinstance(NewStyleClass, type)
  True
Python 3:

  >>> class Class: pass
  >>> isinstance(Class, type)
  True
Old-style classes were kind of their own thing in their own space, but with new-style classes, classes are to `type` as instances are to `object`, and I don’t recall there being any major 2/3 difference beyond the simple removal of old-style classes.


Python2:

  >>> type(type)
  <type 'type'>
Python3:

  >>> type(type)
  <class 'type'>


The 'class' versus 'type' distinction here is actually arbitrary. The same C level code is responsible for the message that you get from 'type(whatever)' in both Python 2 and Python 3, but in Python 2 it drew a distinction between heap-allocated things (which were reported as 'class') and things that were not heap allocated (which were reported as 'type'). Non heap allocated things had to be created in C; heap allocated things were usually implemented in Python and were usually made with 'class X(base): ...'.

(This change was introduced in Python 3.0a5, bug #2565. Looking at the bug, this is a followup of making the type() of new style classes be reported as 'class ...', but preserving old behavior of type() for built-ins, done in 2001.)


Ah, gotcha. But I don’t think that that’s actually a difference—it’s just a slight terminology change around “type” and “class”, which I think may have been related to tidying up old-style classes. (That is: yeah, if you’re comparing old-style classes, it may have been a difference (I’m not certain), but I believe it’s completely superficial once you’re comparing the recommended form of classes for the last quite a few years of Python 2.)


I agree.

I'm pretty sure the word "class" here comes from the repr for types, in Objects/typeobject.c :

  static PyObject *
  type_repr(PyTypeObject *type)
  {
    ...
      if (mod != NULL && !_PyUnicode_EqualToASCIIId(mod, &PyId_builtins))
          rtn = PyUnicode_FromFormat("<class '%U.%U'>", mod, name);
      else
        rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);
    ...
which is used later on when defining the "type" type:

  PyTypeObject PyType_Type = {
      PyVarObject_HEAD_INIT(&PyType_Type, 0)
      "type",                                     /* tp_name */
       ...
      (reprfunc)type_repr,                        /* tp_repr */
That is, Python 3 has no actual "class" type, so it's not correct to say that '"type" is an instance of "class."'

(I could be wrong - I'm no expert at the Python internals.)


Looks like a slight difference in debugging text printed by a single function, not something fundamental about the whole type system.


I was working on writing the same thing, though less clearly. :)

As a minor note, in Python 2, types.ClassType was a "thing":

  >>> import types
  >>> types.ClassType is type
  False
  >>> isinstance(types.ClassType, type)
  True
  >>> my_class = types.ClassType("spam", bases=(), dict={})
  >>> my_class
  <class __main__.spam at 0x106732670>
I don't remember the details any more, but it looks like it was the base for class for old-style classes. Using your class definitions:

  >>> isinstance(OldStyleClass, types.ClassType)
  True
  >>> isinstance(NewStyleClass, types.ClassType)
  False

Python 3 replaced that functionality with types.new_class(), which returns an instance of type 'type':

  >>> my_class = types.new_class("spam")
  >>> isinstance(my_class, type)
  True 
  >>> my_class
  <class 'types.spam'>
  >>> type(my_class)
  <class 'type'>
As I recall, in the early 1.x days it wasn't apparent that the class/type dichotomy was a problem. It took a lot of work during the 2.x era to bring them together.


Thanks for the correction; it’s about five years since I’ve done any serious work in Python, and six or seven since I last did any involved metaprogramming, and I assiduously avoided old-style classes even then, and so I had completely forgotten about types.ClassType. Python 2.4 was the oldest version I ever worked with, also.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: