Why is __init__() always called after __new__()?
Use
__new__
when you need to control
the creation of a new instance.
Use
__init__
when you need to control initialization of a new instance.
__new__
is the first step of instance creation. It's called first, and is
responsible for returning a new
instance of your class.
In contrast,
__init__
doesn't return anything; it's only responsible for initializing the
instance after it's been created.In general, you shouldn't need to
override__new__
unless you're
subclassing an immutable type like
str, int, unicode or tuple.
From April 2008 post: When to use __new__
vs. __init__
? on mail.python.org.
You should consider that what you are trying to do is usually done with a Factory and that's the best way to do it. Using __new__
is not a good clean solution so please consider the usage of a factory. Here's a good example: ActiveState Fᴀᴄᴛᴏʀʏ ᴘᴀᴛᴛᴇʀɴ Recipe.
`__new__` and `__init__` on class and object
The biggest part of the picture you're probably missing is that __new__
is a staticmethod, special-cased to be one even if you don't use the @staticmethod
decorator.
When calling a method through super()
, super()
performs the same kind of argument binding that would be performed normally for that kind of method (using the descriptor protocol). For a staticmethod like __new__
, that means no arguments are automatically bound, so cls
has to be passed explicitly. For an instance method like __init__
, that means self
is bound automatically, which is why you don't have to pass self
to super().__init__
.
Why is __init__ not called after __new__ SOMETIMES
From the documentation:
If
__new__()
does not return an instance of cls, then the new instance’s__init__()
method will not be invoked.
This is to allow __new__()
to return a new instance of a different class, which has its own __init__()
to be called instead. You will need to detect if you're creating a new cls, and call the appropriate constructor instead if not.
What can `__init__` do that `__new__` cannot?
Everything you can do in __init__
can also be done in __new__
.
Then, why use __init__
?
Because you don't have to store instance in variable (obj
in your example code), and later bother returning it. You can focus on what you realy want to do – initializing mutable object.
python: error when running __new__? not invoking __init__
__init__()
will only be invoked if your __new__()
returns something that it can be validly invoked on - namely, an instance of the class.
In your example, you're returning the class itself.
This is one way you can do it:
To create an instance of your class, and return it instead of returning the class itself:
from abc import ABCMeta, abstractmethod
class MyConfig(metaclass=ABCMeta):
def __new__(cls, *args, **kwargs):
instance = super(MyConfig, cls).__new__(cls, *args, **kwargs)
print("Config new")
return instance
def __init__(self, *args, **kwargs):
print("Config init")
class MyConfiguration(MyConfig):
def __init__(self, *args, **kwargs):
super(MyConfiguration, self).__init__(*args, **kwargs)
print("Configuration init")
if __name__ == '__main__':
c = MyConfiguration()
Output:
Config new
Config init
Configuration init
Why does __init__ not get called if __new__ called with no args
The constructor (User()
) is responsible for calling the allocator (User.__new__()
) and the initializer (User.__init__()
) in turn. Since the constructor is never invoked, the initializer is never called.
__new__ and __init__ in Python
how I should structure the class using
__init__
and__new__
as they are different and both accepts arbitrary arguments besides default first argument.
Only rarely will you have to worry about __new__
. Usually, you'll just define __init__
and let the default __new__
pass the constructor arguments to it.
self
keyword is in terms of name can be changed to something else? But I am wonderingcls
is in terms of name is subject to change to something else as it is just a parameter name?
Both are just parameter names with no special meaning in the language. But their use is a very strong convention in the Python community; most Pythonistas will never change the names self
and cls
in these contexts and will be confused when someone else does.
Note that your use of def __new__(tuple)
re-binds the name tuple
inside the constructor function. When actually implementing __new__
, you'll want to do it as
def __new__(cls, *args, **kwargs):
# do allocation to get an object, say, obj
return obj
Albeit I said I want to return
tuple
, this code works fine and returned me[1,2,3]
.
MyClass()
will have the value that __new__
returns. There's no implicit type checking in Python; it's the responsibility of the programmer to return the correct type ("we're all consenting adults here"). Being able to return a different type than requested can be useful for implementing factories: you can return a subclass of the type requested.
This also explains the issubclass
/isinstance
behavior you observe: the subclass relationship follows from your use of class MyClass(tuple)
, the isinstance
reflects that you return the "wrong" type from __new__
.
For reference, check out the requirements for __new__
in the Python Language Reference.
Edit: ok, here's an example of potentially useful use of __new__
. The class Eel
keeps track of how many eels are alive in the process and refuses to allocate if this exceeds some maximum.
class Eel(object):
MAX_EELS = 20
n_eels = 0
def __new__(cls, *args, **kwargs):
if cls.n_eels == cls.MAX_EELS:
raise HovercraftFull()
obj = super(Eel, cls).__new__(cls)
cls.n_eels += 1
return obj
def __init__(self, voltage):
self.voltage = voltage
def __del__(self):
type(self).n_eels -= 1
def electric(self):
"""Is this an electric eel?"""
return self.voltage > 0
Mind you, there are smarter ways to accomplish this behavior.
Related Topics
What Is the Eafp Principle in Python
How to Convert a .Py to .Exe For Python
"Inconsistent Use of Tabs and Spaces in Indentation"
"Pip Install Unroll": "Python Setup.Py Egg_Info" Failed With Error Code 1
Bare Asterisk in Function Arguments
How to Resize an Image Using Pil and Maintain Its Aspect Ratio
How to Set Environment Variables in Python
Typeerror: 'List' Object Is Not Callable in Python
How to Parallelize a Simple Python Loop
"Large Data" Workflows Using Pandas
How to Execute a String Containing Python Code in Python
Annotate Bars With Values on Pandas Bar Plots