In Python 2, you'll notice that built-in types are sometimes distinct from user-defined types (classes):
>>> type(str)
<type 'type'>
>>> type("Mahmud")
<type 'str'>
>>> str
<type 'str'>
>>> class OldStyleClass:
... pass
...
>>> type(OldStyleClass)
<type 'classobj'>
>>> type(OldStyleClass())
<type 'instance'>
>>> OldStyleClass
<class ...OldStyleClass at 0x...>
>>> class NewStyleClass(object):
... pass
...
>>> type(NewStyleClass)
<type 'type'>
>>> type(NewStyleClass())
<class 'NewStyleClass'>
>>> NewStyleClass
<class 'NewStyleClass'>
So we have three distinct cases:
- builtin types like
str
- old style classes
- new style classes which inherit from
object
.
type(X) X type(X())
----------------- ------------------ -----------------
builtin <type 'type'> <type 'X'> <type 'X'>
old style <type 'classobj'> <class X at 0x...> <type 'instance'>
new style <type 'type'> <class 'X'> <class 'X'>
The differences between these cases are subtle and have become less important over time. In earlier Python versions, the internal representation affected the reflection capabilities. A remnant of these issues in Python 2.7 is that type(X()) == X
is false when X is an old-style class!
So for Python 2.x there are some differences between builtin-types and user-defined classes, even though all of them can be used as classes (instantiated, inherited from, …). I consider the author's statement correct, though slightly misleading. It would be more correct to say:
The class
keyword allows programmers to define additional classes.
or
Each value has a class or type which contains available methods. You can add your own classes with the class
keyword.
(Of course, a class
definition is not the only way to define a new class. The type(…)
constructor comes to mind, as would C extensions.)
In Python 3, these three cases have been combined and there is no visible difference between built-in and user-defined classes.