Note à propos de la différence entre l' __new__ et __init__
Avant d'expliquer qu'il manque des fonctionnalités revenons à la définition de l' __new__
et __init__
:
__new__ est la première étape de création de l'instance. Il est appelé en premier, et est chargée de renvoyer une nouvelle instance de votre classe.
Toutefois, le __init__ ne retourne rien, c'est seulement responsable pour
l'initialisation de l'instance après avoir été créée.
Conséquences du remplacement de __init__ de __new__
Principalement vous viendrait à perdre en flexibilité. Vous obtenez beaucoup de la sémantique des maux de tête et lâche la séparation de initializatin et de la construction (en joignant __new__ and
init nous sont à joindre à la construction et initialisation en une seule étape,...).
Jetons un coup d'oeil sur l'extrait de code ci-dessous:
class A(object):
some_property = 'some_value'
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls, *args, **kwargs)
obj.some_property = cls.some_property
return obj
class B(A):
some_property = 2
def __new__(cls, *args, **kwargs):
obj = super(B, cls).__new__(cls)
return obj
Les conséquences de déménagement __init__
d'actions en __new__
:
Initialiser B
avant A
: Lorsque vous utilisez __new__
méthode de __init__
votre première étape de création de la nouvelle instance de B est l'appel d' A.__new__
comme effet secondaire vous ne pouvez pas initialiser B
avant A
est initialisé ( accès et d'attribuer certaines propriétés à nouveau B exemple). À l'aide d' __init__
vous donne une telle flexibilité.
Perdre le contrôle sur l'initialisation de l'ordre: imaginons que vous avez B_N
a hérité de deux classes (A_N1
, A_N2
), maintenant vous manquez de contrôle de la commande d'initialisation de la nouvelle instance de l' B_N
(ce qui est l'ordre vous allez initialiser les instances ? il pourrait être question... ce qui est bizarre.)
Propriétés et méthodes de gâchis: vous manquez d'accès à l' A.some_property
(cls
serait égale à B
alors que l'instanciation de la nouvelle instance de l' B
. Toutefois accéder directement à de la A.some_property
est possible, mais je suppose qu'il est au moins bizarre pour accéder à des propriétés au sein de la classe à travers nom de la classe et non à l'aide de classmethods
).
Vous ne pouvez pas re-initialiser une existaient instance sans avoir à créer de l'un ou de mise en œuvre une logique spéciale pour cela ( merci à @platinhom pour l'idée )
Que peut - __init__
faire __new__
ne le peuvent pas?
Il n'y a pas d'actions qui ne peuvent être réalisés en __new__
et ne peut, en __init__
, parce que les actions qu' __init__
effectue est un sous-ensemble des actions qui peuvent être effectuées par __new__
.
Un moment intéressant de Python Docs, le Décapage et la unpickling normal des instances de classe#objet.getinitargs concernant le moment __init__
pourrait être utile:
Lorsqu'un marinés instance de classe est unpickled, son init() est normalement pas invoquée.