Subclassing built-in types is straightforward. Actually we have been
doing it all along (whenever we subclass
<type 'object'>). Some built-in
types.FunctionType, for example) are not
subclassable (not yet, at least). However, here we talk about
'tuple'> and other basic data types.
Example 3.3. Subclassing <type 'list'>
A regular class statement.
Define the method to
be overridden. In this case we will convert all items passed through
Upcall to the base if required.
Append a float and...
watch it automatically become an integer.
Otherwise, it behaves like any other list.
This doesn't go
through append. We would have to define
We can set attributes
on our instance. This is because it has a
Basic lists do not have
__dict__ (and so no
user-defined attributes), but ours does. This is usually not a problem
and may even be what we want. If we use a very
large number of
MyLists, however, we could optimize
our program by telling Python not to create the
__dict__ for instances of
Example 3.4. Using
__slots__ for optimization
class MyList(list): "A list subclass disallowing any user-defined attributes" __slots__ =  ml = MyList() ml.color = 'red' # raises exception! class MyListWithFewAttrs(list): "A list subclass allowing specific user-defined attributes" __slots__ = ['color'] mla = MyListWithFewAttrs() mla.color = 'red' mla.weight = 50 # raises exception!
Setting any attribute on this raises an exception.
Now, if an attribute has space reserved, it can be used.
Otherwise, it cannot. This will raise an exception.
The purpose and recommended use of
is for optimization. After a type is defined, its slots cannot be
changed. Also, every subclass must define
otherwise its instances will end up having
We can create a list even by instantiating it like any other type:
list([1,2,3]). This means
list.__init__() accepts the same argument (i.e. any
iterable) and initializes a list. We can customize initialization in a
subclass by redefining
__init__() on the
Tuples are immutable and different from lists. Once an instance
is created, it cannot be changed. Note that the instance of a type
already exists when
__init__() is called (in fact
the instance is passed as the first argument). The
__new__() static method of a type is called to
create an instance of the type. It is passed the
type itself as the first argument, and passed through other initial
arguments (similar to
__init__()). We use this to
customize immutable types like a tuple.
Example 3.5. Customizing creation of subclasses
For a list, we massage the arguments and hand them over to |
For a tuple, we have to override |
__new__() method is not special to immutable
types, it is used for all types. It is also converted to a static
method automatically by Python (by virtue of its name).