[Tutor] Inherit from int?

Alan Gauld alan.gauld at btinternet.com
Sun May 13 09:57:29 CEST 2007


"John Fouhy" <john at fouhy.net> wrote

> Subclassing int and other types is a bit special.  Check out this
> page; it may help you:
> http://www.python.org/download/releases/2.2.3/descrintro/#__new__
>

In case others have the same problem...
John's link didn't work for me but I eventually found this
relevant snippet here:
http://www.python.org/download/releases/2.2/descrintro/#subclassing

--------------------------------
Recall that you create class instances by calling the class. When
the class is a new-style class, the following happens when it is 
called.
First, the class's __new__ method is called, passing the class itself
as first argument, followed by any (positional as well as keyword)
arguments received by the original call. This returns a new instance.
Then that instance's __init__ method is called to further initialize 
it.
(This is all controlled by the __call__ method of the metaclass, by 
the way.)
Here is an example of a subclass that overrides __new__ - this
is how you would normally use it.

    >>> class inch(float):
    ...     "Convert from inch to meter"
    ...     def __new__(cls, arg=0.0):
    ...         return float.__new__(cls, arg*0.0254)
    ...
    >>> print inch(12)
    0.3048
    >>>
This class isn't very useful (it's not even the right way to go about
unit conversions) but it shows how to extend the constructor of
an immutable type. If instead of __new__ we had tried to
override __init__, it wouldn't have worked:

    >>> class inch(float):
    ...     "THIS DOESN'T WORK!!!"
    ...     def __init__(self, arg=0.0):
    ...         float.__init__(self, arg*0.0254)
    ...
    >>> print inch(12)
    12.0
    >>>
The version overriding __init__ doesn't work because the float
type's __init__ is a no-op: it returns immediately, ignoring its
arguments.

All this is done so that immutable types can preserve their
immutability while allowing subclassing. If the value of a float 
object
were initialized by its __init__ method, you could change the value
of an existing float object! For example, this would work:

    >>> # THIS DOESN'T WORK!!!
    >>> import math
    >>> math.pi.__init__(3.0)
    >>> print math.pi
    3.0
    >>>





More information about the Tutor mailing list