What arguments are passed to the __new__ method ?

Terry Reedy tjreedy at udel.edu
Tue Mar 1 15:27:48 EST 2016


On 3/1/2016 12:24 PM, ast wrote:
> Hello
>
> It's not clear to me what arguments are passed to the
> __new__ method.

The objects passed to any function are the objects that are passed.  The 
type and number of objects that *should be* passed depends on the 
signature of the function.

If class C defines __new__, then C.__new__ will receive as args C and 
all args passed in a C(...) call.  So the C(...) call should have args 
that match those expected by __new__.  If C also defines __init__, it 
will get the same args other than self replacing cls and thus it should 
have the same signature.

The case is covered by in the entry for __new__ in
https://docs.python.org/3/reference/datamodel.html#basic-customization

"If __new__() returns an instance of cls, then the new instance’s 
__init__() method will be invoked like __init__(self[, ...]), where self 
is the new instance and the remaining arguments are the same as were 
passed to __new__()."

> class Premiere:
>     def __new__(cls, price):
>          return object.__new__(cls)

This matches "Typical implementations create a new instance of the class 
by invoking the superclass’s __new__() method using super(currentclass, 
cls).__new__(cls[, ...]) with appropriate arguments and then modifying 
the newly-created instance as necessary before returning it." 
object.__new__ only takes the cls parameter.

>     def __init__(self, price):
>             pass
> p = Premiere(1000)
>
> No errors, so it seems that 2 arguments are passed
> to __new__, cls and price,

and 2 arguments are passed to __init__, self and price -- as documented.

> But if i do:

> class Premiere:
>     def __new__(cls, price):
>         return object.__new__(cls, price)

You get an error in current python because you sent an extra arg to 
object.__new__.  If __new__ calls a superclass __new__, then it should 
only pass the args expected.  At one time, object.__new__ would have 
accepted the price arg and ignored it.  This is no longer true

>     def __init__(self, price):
>         pass
> p = Premiere(1000)
>
> it fails. It is strange because according to me it is equivalent to:

Well, 'you' is wrong ;-), because in the following case, 
Premiere.__new__ is object.__new__, which has a different signature than 
__new__ above.

> class Premiere:
>     def __init__(self, price):
>          pass
> p = Premiere(1000)
>
> which is OK.

Premiere is callable because it inherits object.__call__.  That 
function, or the implementation of the CALL FUNCTION bytecode, must 
notice that Premiere.__new__ is object.__new__, by inheritance, and only 
pass Premiere and not 1000.

The doc entry for __init__ says "The arguments are those passed to the 
class constructor expression."  (The latter is the expression in the 
code that results in the class call.)  This is always true.  But since 
the signature of object.__new__ was restricted, the claim that the same 
args are sent to __new__ and __init__ seems not to be true.

I may open a new doc issue.

-- 
Terry Jan Reedy





More information about the Python-list mailing list