Distinction between “class” and “type”

Steven D'Aprano steve at pearwood.info
Sat May 14 01:05:20 EDT 2016


On Fri, 13 May 2016 03:07 pm, Ben Finney wrote:

> Howdy all,
> 
> Ever since Python's much-celebrated Grand Unification of classes and
> types, I have used those terms interchangeably: every class is a type,
> and every type is a class.
> 
> That may be an unwise conflation. With the recent rise of optional type
> annotation in Python 3, more people are speaking about the important
> distinction between a class and a type.
[...]
> As a Bear of Little Brain, this leaves me clueless. What is the
> distinction Guido alludes to, and how are Python classes not also types?
> 
> And why is this distinction important, and who moved my cheesecake?

You're not alone. Unfortunately, this confusion is endemic in IT and on the
internet. People use types all the time, but without understanding that
there are (at least) two related but distinct meanings for the word.

Even though it isn't specifically about this distinction, you should start
by reading this essay about the distinction between static and dynamic
typing here:

https://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/

Then you should read Guido's PEP 483 on "gradual typing":

https://www.python.org/dev/peps/pep-0483/


And this answer on Stackoverflow:

http://stackoverflow.com/a/25114770

(Note that despite the question specifying language agnostic answers, the
second most highly-rated answer is language specific.)


The Wikipedia article is heavy going, but worth reading:

https://en.wikipedia.org/wiki/Type_theory


As Python programmers, the simplest way to look at this question is:

(1) Class (also known as a "type", although for the avoidance of confusion I
shall avoid that terminology here) in the Python sense is an entity which
tells the interpreter what methods and attributes a value has. In other
words, classes define behaviour.

In Python classes are "first-class values" and can be created on the fly,
bound to names, put inside lists, etc. This is not essential to the concept
though, many languages, such as Java, do not treat classes as first-class.

Unfortunately, for historical reasons, the function[1] which returns the
class of a value is called "type()". And the class of all classes (the
metaclass) is also called "type". Which made type and class synonyms from
Python 2.2 onwards.


(2) Type, in the PEP 483/484 sense, is a label which tells the static
type-checker what kind of values are acceptable in a particular place. This
is the "type theory" sense as in the Wikipedia article.

In principle these PEP 484 types could be completely abstract, but Python's
typing module will generally use classes (sense 1 above) to implement these
label.


(3) In Python especially, the differences between (1) and (2) are more
theoretical than practical, but there are a couple of obvious exceptions:

- Union types should be considered a purely abstract label. (In practice,
they'll actually be implemented as a class, but that's just an
implementation detail.) Unions cannot be instantiated, nor subclassed. For
example, take this example:


py> import typing
py> Foo = typing.Union[str, int]

Foo is now a label to tell the type-checker you will accept "a str, or an
int, but nothing else". It is *not* a subclass of str and int. There is no
such thing as an instance of Foo, nor can you subclass it. If you try, you
get a TypeError:

py> Foo() 
[...]
TypeError: Cannot instantiate <class 'typing.UnionMeta'>

class Bar(Foo): pass
[...]
TypeError: Cannot subclass typing.Union[str, int]

This is from Python 3.6 pre-alpha. The messages may change in the future.

Foo is only used as a purely abstract label to tell the type-checker to
accept either a str, or an int. So in that sense, although the Python
implementation of Foo is a class object, that's just a detail of the
implementation.


- The other obvious example is Any. Like Unions, Any cannot be instantiated
or subclassed and is intended as a purely abstract label for "anything at
all". One can consider Any to be the equivalent of a Union of "all possible
types", and it basically exists for the type-checker to record a state of
maximum ignorance. ("I don't know what this will be, it could be
anything.")


So types and classes essentially have different purposes, even though they
overlap. Types (in this "type theory", PEP 484 sense) are for proving
compile-time facts about code. Classes (in Python) are for specifying the
behaviour and implementation of objects.





[1] Actually, the function "type()" and the class "type" are implemented as
the same object, which does two different things depending on how many
arguments it gets. With one argument, type(x) returns the class of x. With
three arguments, type(name, bases, namespace) creates and returns a new
class.


-- 
Steven




More information about the Python-list mailing list