Difference between type and class

N

Nikolaus Rath

Hello,

Can someone explain to me the difference between a type and a class?
After reading http://www.cafepy.com/article/python_types_and_objects/
it seems to me that classes and types are actually the same thing:

- both are instances of a metaclass, and the same metaclass ('type')
can instantiate both classes and types.
- both can be instantiated and yield an "ordinary" object
- I can even inherit from a type and get a class

So why does Python distinguish between e.g. the type 'int' and the
class 'myclass'? Why can't I say that 'int' is a class and 'myclass'
is a type?

I hope I have managed to get across the point of my confusion...


Thanks in advance,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
O

oj

So why does Python distinguish between e.g. the type 'int' and the
class 'myclass'? Why can't I say that 'int' is a class and 'myclass'
is a type?

I might be wrong here, but I think the point is that there is no
distinction. A class (lets call it SomeClass for this example) is an
object of type 'type', and an instance of a class is an object of type
'SomeClass'.

So int is a type, but if you have an int variable, its type is int.

Same for your classes.

This is, ignoring old style classes. Make sure all your classes
inherit from object to get new style classes.
 
T

Thomas Troeger

Can someone explain to me the difference between a type and a class?

If your confusion is of a more general nature I suggest reading the
introduction of `Design Patterns' (ISBN-10: 0201633612), under
`Specifying Object Interfaces'.

In short: A type denotes a certain interface, i.e. a set of signatures,
whereas a class tells us how an object is implemented (like a
blueprint). A class can have many types if it implements all their
interfaces, and different classes can have the same type if they share a
common interface. The following example should clarify matters:

class A:
def bar(self):
print "A"

class B:
def bar(self):
print "B"

class C:
def bla(self):
print "C"

def foo(x):
x.bar()

you can call foo with instances of both A and B, because both classes
share a common type, namely the type that has a `bar' method), but not
with an instance of C because it has no method `bar'. Btw, this example
shows the use of duck typing (http://en.wikipedia.org/wiki/Duck_typing).

HTH,
Thomas.
 
N

Nikolaus Rath

Thomas Troeger said:
If your confusion is of a more general nature I suggest reading the
introduction of `Design Patterns' (ISBN-10: 0201633612), under
Specifying Object Interfaces'.

In short: A type denotes a certain interface, i.e. a set of
signatures, whereas a class tells us how an object is implemented
(like a blueprint). A class can have many types if it implements all
their interfaces, and different classes can have the same type if they
share a common interface. The following example should clarify
matters:

class A:
def bar(self):
print "A"

class B:
def bar(self):
print "B"

class C:
def bla(self):
print "C"

def foo(x):
x.bar()

you can call foo with instances of both A and B, because both classes
share a common type, namely the type that has a `bar' method), but not
with an instance of C because it has no method `bar'. Btw, this
example shows the use of duck typing
(http://en.wikipedia.org/wiki/Duck_typing).

That would imply that I cannot create instances of a type, only of
a class that implements the type, wouldn't it?

But Python denotes 'int' as a type *and* I can instantiate it.



Still confused,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
N

Nikolaus Rath

oj said:
I might be wrong here, but I think the point is that there is no
distinction. A class (lets call it SomeClass for this example) is an
object of type 'type', and an instance of a class is an object of type
'SomeClass'.

But there seems to be a distinction:
.... pass
.... <type 'int'>

why doesn't this print
.... pass
.... <type 'int'>

or
.... pass
.... <class 'int'>

If there is no distinction, how does the Python interpreter know when
to print 'class' and when to print 'type'?


Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
M

Maric Michaud

Le Thursday 31 July 2008 14:30:19 Nikolaus Rath, vous avez écrit :
But there seems to be a distinction:

... pass
...


<type 'int'>

why doesn't this print


... pass
...


<type 'int'>

or


... pass
...


<class 'int'>

If there is no distinction, how does the Python interpreter know when
to print 'class' and when to print 'type'?

There are some confusion about the terms here.

Classes are instances of type 'type', but types are both instances and
subclasses of 'type'.
This recursivity is the base of the object model.

An instance of 'type' is a class (or a new type), but instances of a classes
are not. 'type' is a metatype in term of OO.

What the <type int> means is that int is not a user type but a builtin type,
instances of int are not types (or classes) but common objects, so its nature
is the same as any classes.

The way it prints doesn't matter, it's just the __repr__ of any instance, and
...: class __metaclass__(type) :
...: def __repr__(self) : return "<type A>"
...:
...:
...[2]: said:
[3]: type('toto', (object,), {})
...[3]: <class '__main__.toto'>
 
T

Thomas Troeger

That would imply that I cannot create instances of a type, only of
a class that implements the type, wouldn't it?

But Python denotes 'int' as a type *and* I can instantiate it.

Now I start getting confused also ;-)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__',
'__delattr__', '__div__', '__divmod__', '__doc__', '__float__',
'__floordiv__', '__getattribute__', '__getnewargs__', '__hash__',
'__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__',
'__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__',
'__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__',
'__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__',
'__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__',
'__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__',
'__rxor__', '__setattr__', '__str__', '__sub__', '__truediv__', '__xor__']

I think in Python everything is implemented as a class which makes
sense. AFAIK you can implement a certain interface in a custom class and
it behaves like, for example, a builtin integer. But I guess one of the
gurus can clarify this matter with an appropriate URL ;-)
 
M

Maric Michaud

Le Thursday 31 July 2008 13:32:39 Thomas Troeger, vous avez écrit :
De :
Thomas Troeger <[email protected]>  (Aioe.org NNTP Server)
À :
(e-mail address removed)
Date :
Aujourd'hui 13:32:39
 


If your confusion is of a more general nature I suggest reading the
introduction of `Design Patterns' (ISBN-10: 0201633612), under
`Specifying Object Interfaces'.

In short: A type denotes a certain interface, i.e. a set of signatures,
whereas a class tells us how an object is implemented (like a
blueprint). A class can have many types if it implements all their
interfaces, and different classes can have the same type if they share a
common interface. The following example should clarify matters:

Of course, this is what a type means in certain literature about OO
(java-ish), but this absolutely not what type means in Python. Types are a
family of object with a certain status, and they're type is "type",
conventionnaly named a metatype in standard OO.

There are three sort of objects in Python, in an inclusive order :

- ordinary object, or instance, they could not be instantiated or subclassed
(in general), and are all an instance of type "object" (or a subclass of it).

- types, or classes, are all instance of type 'type' (or a subclass of it),
they can be instantiated and they produce objects (ordinary object in
general) with theirslef as a type.

- metatypes or metaclass, are subclasses of "type", their instances are new
types.

For all tjis work together you must admit the following recursivity :

'type' is both a subclass and an instance of 'object' while 'object' is an
instance of 'type'.
 
N

Nikolaus Rath

Maric Michaud said:
Of course, this is what a type means in certain literature about OO
(java-ish), but this absolutely not what type means in Python. Types
are a family of object with a certain status, and they're type is
"type", conventionnaly named a metatype in standard OO.
[...]

Hmm. Now you have said a lot about Python objects and their type, but
you still haven't said what a type actually is (in Python) and in what
way it is different from a class. Or did I miss something?


Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
N

Nikolaus Rath

Maric Michaud said:
Le Thursday 31 July 2008 14:30:19 Nikolaus Rath, vous avez écrit :

There are some confusion about the terms here.

Classes are instances of type 'type',

Could you please clarify what you mean with 'instance of type X'? I
guess you mean that 'y is an instance of type X' iif y is constructed
by instantiating X. Is that correct?
What the <type int> means is that int is not a user type but a
builtin type, instances of int are not types (or classes) but common
objects, so its nature is the same as any classes.

The way it prints doesn't matter, it's just the __repr__ of any instance, and
the default behavior for instances of type is to return '<class XX>', but it
can be easily customized.

But 'int' is an instance of 'type' (the metaclass):
<type 'type'>

so it should also return '<class int>' if that's the default behavior
of the 'type' metaclass.

I think that to get '<type int>' one would have to define a new
metaclass like this:

def type_meta(type):
def __repr__(self)
return "<type %s>" % self.__name__

and then one should have int.__class__ == type_meta. But obviously
that's not the case. Why?


Moreover:
.... pass
.... <class '__main__.myint'>

despite int and myint having the same metaclass. So if the
representation is really defined in the 'type' metaclass, then
type.__repr__ has to make some kind of distinction between int and
myint, so they cannot be on absolute equal footing.



Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
M

Maric Michaud

Le Thursday 31 July 2008 16:46:28 Nikolaus Rath, vous avez écrit :
Maric Michaud said:
Of course, this is what a type means in certain literature about OO
(java-ish), but this absolutely not what type means in Python. Types
are a family of object with a certain status, and they're type is
"type", conventionnaly named a metatype in standard OO.

[...]

Hmm. Now you have said a lot about Python objects and their type, but
you still haven't said what a type actually is (in Python) and in what
way it is different from a class. Or did I miss something?

This paragraph ?

"""
- types, or classes, are all instance of type 'type' (or a subclass of it),
they can be instantiated and they produce objects (ordinary object in
general) with theirslef as a type.
"""

Maybe it's still unclear that "types" and "classes" *are* synonyms in Python.
 
N

Nikolaus Rath

Maric Michaud said:
Le Thursday 31 July 2008 16:46:28 Nikolaus Rath, vous avez écrit :
Maric Michaud said:
Can someone explain to me the difference between a type and a class?

If your confusion is of a more general nature I suggest reading the
introduction of `Design Patterns' (ISBN-10: 0201633612), under
`Specifying Object Interfaces'.

In short: A type denotes a certain interface, i.e. a set of signatures,
whereas a class tells us how an object is implemented (like a
blueprint). A class can have many types if it implements all their
interfaces, and different classes can have the same type if they share a
common interface. The following example should clarify matters:

Of course, this is what a type means in certain literature about OO
(java-ish), but this absolutely not what type means in Python. Types
are a family of object with a certain status, and they're type is
"type", conventionnaly named a metatype in standard OO.

[...]

Hmm. Now you have said a lot about Python objects and their type, but
you still haven't said what a type actually is (in Python) and in what
way it is different from a class. Or did I miss something?

This paragraph ?

"""
- types, or classes, are all instance of type 'type' (or a subclass of it),

Well, I couldn't quite make sense of '..are instance of type...'
without knowing what you actually meant with "type* in this context,
but...
Maybe it's still unclear that "types" and "classes" *are* synonyms
in Python.

...in this case it becomes clear. Then my question reduces to the one
in the other post (why do 'int' and 'myint' have different __repr__
results).


Already thanks for your help,


-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
M

Maric Michaud

Le Thursday 31 July 2008 17:00:51 Nikolaus Rath, vous avez écrit :
Could you please clarify what you mean with 'instance of type X'? I
guess you mean that 'y is an instance of type X' iif y is constructed
by instantiating X. Is that correct?

Correct, you can verify this with the isinstance builtin :
...[1]: True
...[2]: True
...[3]: True
...:
...[5]: True


But 'int' is an instance of 'type' (the metaclass):

<type 'type'>

so it should also return '<class int>' if that's the default behavior
of the 'type' metaclass.

The fact that a class is an instance of type, which it is always true, doesn't
mean its metaclass is "type", it could be any subclass of type :
...: class __metaclass__(type) :
...: def __repr__(self) : return "<type A>"
...:
...:
...[7]: True
[8]: A.__class__
...[8]: said:
[9]: issubclass(A.__class__, type)
...[9]: True

I think that to get '<type int>' one would have to define a new
metaclass like this:

def type_meta(type):
    def __repr__(self)
         return "<type %s>" % self.__name__

and then one should have int.__class__ == type_meta. But obviously
that's not the case. Why?

Moreover:

...    pass
...


True

*is* comparaison fits better here.
<class '__main__.myint'>

despite int and myint having the same metaclass. So if the
representation is really defined in the 'type' metaclass, then
type.__repr__ has to make some kind of distinction between int and
myint, so they cannot be on absolute equal footing.

You're right, type(int) is type, the way it renders differently is a detail of
its implementation, you can do things with builtin types (written in C) you
coudn't do in pure python, exactly as you couldn't write recursive types
like 'object' and 'type'.
 
N

Nikolaus Rath

Maric Michaud said:
The fact that a class is an instance of type, which it is always true, doesn't
mean its metaclass is "type", it could be any subclass of type :

Yes, that is true. But it's not what I said above (and below).
'obj.__class__' gives the class of 'obj', so if 'int.__class__ is
type' then 'type' is the class of 'int' and 'int' is *not* an instance
of some metaclass derived from 'type'.
You're right, type(int) is type, the way it renders differently is a
detail of its implementation, you can do things with builtin types
(written in C) you coudn't do in pure python, exactly as you
couldn't write recursive types like 'object' and 'type'.


If it is just a matter of different rendering, what's the reason for
doing it like that? Wouldn't it be more consistent and straightforward
to denote builtin types as classes as well?

And where exactly is this different rendering implemented? Could I
write my own type (in C, of course) and make it behave like e.g.
'int'? I.e. its rendering should be different and not inherited to
subclasses:

<class 'derived>

or would I have to change the implemention of 'type' for this (since
it contains the __repr__ function that renders the type)?


This is of course purely theoretical and probably without any
practical relevance. I'm if I just can't stop drilling, but I think
this is really interesting.


Best,


-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
S

Steven D'Aprano

If your confusion is of a more general nature I suggest reading the
introduction of `Design Patterns' (ISBN-10: 0201633612), under
`Specifying Object Interfaces'.

In short: A type denotes a certain interface, i.e. a set of signatures,
whereas a class tells us how an object is implemented (like a
blueprint). A class can have many types if it implements all their
interfaces, and different classes can have the same type if they share a
common interface.

I fear you're introducing a rather complicated answer for a simple
question. In Python, the simple answer is that built-in objects like int,
float, str etc. are referred to as "types", and custom objects created
using the class keyword are referred to as "classes". This is a
historical distinction that will disappear in time.

We can see that types and classes already have the same type in Python:
.... pass
....<type 'type'>


The following example should clarify matters:

class A:
def bar(self):
print "A"


Alas, you've chosen the worst-possible example to "clarify" matters,
because old-style classic classes are *not* unified with types, and will
disappear in the future:
.... pass
....<type 'classobj'>


So, to the Original Poster:

In Python, new-style classes and types are the same, but it is
traditional to refer to customer objects as "class" and built-in objects
as "types". Old-style classes are different, but you are discouraged from
using old-style classes unless you have a specific reason for needing
them (e.g. backwards compatibility).
 
M

Miles

If it is just a matter of different rendering, what's the reason for
doing it like that? Wouldn't it be more consistent and straightforward
to denote builtin types as classes as well?

Yes, and in Python 3, it will be so:
<class '__main__.myint'>

The reason the distinction is made currently is that before Python
2.2, "types" were built-in (or C extension) classes, and "classes"
were Python classes; it was not possible to subclass built-in types.
That "classic" style of classes are still supported in Python 2.2 and
above (but not in Python 3), by not inheriting from object or any
other built-in. However, for new-style classes, the only distinction
is in the repr.
Traceback (most recent call last):
<class '__main__.newstyle'>

Further reading:

http://www.python.org/download/releases/2.2.3/descrintro/
http://svn.python.org/view?rev=23331&view=rev
http://bugs.python.org/issue2565

-Miles
 
N

Nikolaus Rath

Miles said:
If it is just a matter of different rendering, what's the reason for
doing it like that? Wouldn't it be more consistent and straightforward
to denote builtin types as classes as well?

Yes, and in Python 3, it will be so:
[..]

http://svn.python.org/view?rev=23331&view=rev

That makes matters absolutely clear. Thanks a lot. No more questions
from my side ;-).


Best,

-Nikolaus


--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
N

Nikolaus Rath

Steven D'Aprano said:
So, to the Original Poster:

In Python, new-style classes and types are the same, but it is
traditional to refer to customer objects as "class" and built-in
objects as "types". Old-style classes are different, but you are
discouraged from using old-style classes unless you have a specific
reason for needing them (e.g. backwards compatibility).

I see. Thanks a lot for the explanation.


Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
T

Thomas Troeger

Steven said:
Alas, you've chosen the worst-possible example to "clarify" matters,
because old-style classic classes are *not* unified with types, and will
disappear in the future:

Of course I wanted to write `class A(object)', but I keep forgetting
this one because I'm still used to the old ways...

Will this disappear in Python 3.0., i.e. can you again simply write

class A:

and inherit from object automagically? That would be nice since that's
what most people probably want.
 
M

Matthew Woodcraft

Thomas Troeger said:
Will this disappear in Python 3.0., i.e. can you again simply write

class A:

and inherit from object automagically?

Short answer: yes.

-M-
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,814
Latest member
SpicetreeDigital

Latest Threads

Top