J'ai lu que __init__ ne crée pas l'objet (met de côté la mémoire).
Je n'ai pas trouvé qui s'occupe de la création d'objets. Comment cette création d'objet se produit-elle en interne?
3 Réponses :
Lorsque vous tapez quelque chose comme MyClass () en Python, le runtime Python appellera __new__ sur MyClass , ce qui devrait construire un objet; ceci sera suivi par l'appel de __init__ sur l'objet nouvellement construit. Ainsi, __new__ est appelé "constructeur", et __init__ un "initialiseur". Cette séquence est codée en dehors de Python (en C, dans le cas de CPython). Consultez la documentation Python pour en savoir plus sur __new__ < / a> et __init__ .
Vous recherchez probablement __new__ .
D'un point de vue Python, ce qui se passe est quelque chose comme ce qui suit, en supposant que vous ayez une classe, A , qui hérite directement de object:
Une méthode .__ new__ est appelée object .__ new__ est appelé, avec cls=A Une méthode .__ init__ est appelée, avec des arguments transférés depuis votre A.__new__ Example:
__new__ called with args ('arg',) and kwargs {'kwarg': 1}
__init__ called with args ('arg',) and kwargs {'kwarg': 1}
1
Output:
class A():
def __new__(cls, *args, **kwargs):
print(f'__new__ called with args {args} and kwargs {kwargs}')
return super().__new__(cls) # object.__new__
def __init__(self, *args, **kwargs):
print(f'__init__ called with args {args} and kwargs {kwargs}')
# args are discarded
for key, arg in kwargs.items():
setattr(self, key, arg)
a_instance = A('arg', kwarg=1)
a_instance.kwarg
En général, il n'y a pas besoin de faire n'importe quoi avec __new__ , parce que les objets Python sont généralement mutables , et il n'y a donc aucune distinction entre l'initialisation des attributs d'instance et leur modification.
Le cas d'utilisation principal de surcharger __new__ , d'après mon expérience, c'est quand vous héritez de types immuables, tels que tuple . Dans de tels cas, vous devez initialiser tous les attributs d'instance à la création, et par conséquent __init__ est trop tard.
La définition et l'appel à __new__ sont-ils implicites?
@ak_app Oui, lorsque vous appelez A (* args, ** kwargs) , vous appelez en fait A .__ new __ (* args, ** kwargs) . Les args et kwargs sont transmis à A .__ init__ .
Vous avez un commentaire # tuple .__ new__ , mais vous n'héritez pas réellement de tuple .
@ user2357112 Corrigé, j'ai envisagé d'utiliser un exemple de sous-classe tuple , puis je l'ai jeté, mais j'ai oublié de changer le commentaire.
En guise de réponse courte, la méthode qui crée l'objet est __new__ et __init__ initialise simplement l'objet créé.
Cependant, continuez à lire si vous voulez avoir un aperçu plus détaillé de ce qui se passe quand un objet va être créé en python.
En python 2.x il y avait deux types de classes dans les classes python ancien et nouveau style.
A.__new__ called A.__init__ called
class A(object): # -> don't forget the object specified as base
def __new__(cls):
print "A.__new__ called"
return super(A, cls).__new__(cls)
def __init__(self):
print "A.__init__ called"
A()
Dans les classes anciennes, il y avait Il n'y avait pas de méthode __new__ donc __init__ était le constructeur.
Cependant, en python 3.x, il ne reste qu'une nouvelle classe de style (indépendamment du type de définition que vous choisissez pour votre classe, elle sera héritée de la classe de base "Object"). Dans les classes de style nouveau, les méthodes __new__ et __init__ sont disponibles. __new__ et __init__ sont respectivement le constructeur et l'initialiseur et vous êtes autorisé à les remplacer tous les deux (soyez prudent, vous n'avez généralement pas besoin de remplacer __new__ attendez dans certains cas comme la définition de méta-classes, etc., alors ne la manipulez pas si ce n'est pas nécessaire.)
Enfin, lorsqu'un objet va être créé, le constructeur sera appelé avant l'initialiseur.
class C(object): # A old-style class sample
pass
La sortie sera:
class C: # A old-style class sample
pass