In Python 2, noterai che i tipi built-in sono a volte distinti dai tipi definiti dall'utente (classi):
>>> 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'>
Quindi abbiamo tre casi distinti:
- tipi predefiniti come
str
- classi di vecchio stile
- nuove classi di stile che ereditano da
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'>
Le differenze tra questi casi sono sottili e sono diventate meno importanti nel tempo. Nelle precedenti versioni di Python, la rappresentazione interna influiva sulle capacità di riflessione. Un residuo di questi problemi in Python 2.7 è che type(X()) == X
è falso quando X è una classe vecchio stile!
Quindi per Python 2.x ci sono alcune differenze tra i tipi built-in e le classi definite dall'utente, anche se tutti possono essere usati come classi (istanziati, ereditati da, ...). Considero la dichiarazione dell'autore corretta, anche se leggermente fuorviante. Sarebbe più corretto dire:
The class
keyword allows programmers to define additional classes.
o
Each value has a class or type which contains available methods. You can add your own classes with the class
keyword.
(Naturalmente, una definizione class
non è l'unico modo per definire una nuova classe. Mi viene in mente il costruttore di type(…)
, così come le estensioni C.)
In Python 3, questi tre casi sono stati combinati e non vi è alcuna differenza visibile tra le classi built-in e quelle definite dall'utente.