I\'m a little confused by the following example from the python documentation here.
>>> class inch(float):
... \"Convert from inch to meter\"
...
A little background is needed to answer this question:
object.__new__()
can create a new instances
type of objects, this
kind of objects cannot be subclassed.type
, which can be assigned when passing the type name
cls
to __new__(cls)
as the first argument. class
keyword creats
another kind of objects: classes (a.k.a types), and these kinds of objects
can be subclassed.Now, go back to your example, what
float.__new__(cls, argument)
essentially does is using object.__new__(cls)
to create a new instance (float.__base__
is object
),
assign the type cls
(inch
in this case) to it, and also does something with argument
defined in float.__new__
.
So it is not surprising that it'd work when cls
isn't float
but inch
: the class/type is already created by class inch(float)
, you are just assigning this type to a new instance.
Because inch
is a subclass of float, it satisfies all the requirements that the float.__new__()
instance factory has. It is the job of the __new__(cls) static method to create instances of the first argument, not of it's 'own' class.
Note the word 'static method' there. The __new__
factory is really just a specialist function tied to a class only for inheritance reasons. In other words, it is a function that plays well in a object-oriented hierarchy. You are supposed to find it via super()
or perhaps call it directly (as done here). The following would actually be a little more pythonic:
def __new__(cls, arg=0.0):
return super(inch, cls).__new__(cls, arg*0.0254)
because that would call the 'correct' __new__
function if inch
were to be used in a multiple-inheritance hierarchy; in this simple example it'll end up calling float.__new__
just the same.
So, __new__(cls, ...)
is expected to create an instance of type cls
. Why then tie it to a class at all and not make it a more generic function then? Because in the case of float.__new__(cls, value)
it not only creates a new instance of type cls
, it also sets it's initial value to value
. And in order for that to work, float.__new__(...)
needs to have intimate knowledge of what the float
class looks like. Because inch()
is a subclass of float()
, it has the exact same necessary bits to be a float()
too, and thus when the float.__new__()
factory creates a new inch
instance, all those bits are there to make it a inch()
instance instead.