4 ms·
Sure! In Python 2.x, "class" was an instance of "type." In Python 3.x, "type" is an instance of "class." (This is, of course, an over-simplification of a much m
by legerdemain 6y ago
Sure! In Python 2.x, "class" was an instance of "type." In Python 3.x, "type" is an instance of "class." (This is, of course, an over-simplification of a much more complicated reality.)
- chrismorgan 6y agoCould 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.
- legerdemain 6y agoPython2: >>> type(type) <type 'type'> Python3: >>> type(type) <class 'type'>
- chrismorgan 6y agoAh, 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.)
- eesmith 6y agoI 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.)
- siebenmann 6y agoThe '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.)
- quietbritishjim 6y agoLooks like a slight difference in debugging text printed by a single function, not something fundamental about the whole type system.
- eesmith 6y agoI 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.
- chrismorgan 6y agoThanks 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.