Quel est le but du mot self
en Python? Je comprends qu'il se réfère à l'objet spécifique créé à partir de cette classe, mais je ne vois pas pourquoi il doit explicitement être ajouté à chaque fonction en tant que paramètre. Pour illustrer ceci, dans Ruby, je peux le faire:
class myClass
def myFunc(name)
@name = name
end
end
Ce que je comprends assez facilement. Cependant, dans Python, je dois inclure self
:
class myClass:
def myFunc(self, name):
self.name = name
Quelqu'un peut-il me parler à travers ça? Ce n'est pas quelque chose que j'ai rencontré dans mon expérience (certes limitée).
La raison pour laquelle vous devez utiliser self.
est que Python n'utilise pas la syntaxe @
pour faire référence aux attributs d'instance. Python a décidé de faire des méthodes de manière à ce que l'instance à laquelle appartient la méthode soit passée automatiquement, mais pas reç automatiquement: le premier paramètre de method est l'instance à laquelle la méthode est appelée. Cela rend les méthodes entièrement identiques aux fonctions, et laisse le nom réel à utiliser (bien que self
soit la convention, et les gens vous désapprouveront généralement lorsque vous utiliserez autre chose.) self
est pas spécial pour le code, c'est juste un autre objet.
Python aurait pu faire autre chose pour distinguer les noms normaux des attributs - une syntaxe spéciale comme Ruby a, ou nécessitant des déclarations comme C++ et Java do, ou peut-être quelque chose d'encore plus différent - mais ça n'a pas. Python est tout pour rendre les choses explicites, rendre évident ce qui est quoi, et bien qu'il ne le fasse pas entièrement partout, il le fait par exemple pour les attributs. C'est pourquoi l'attribution à un attribut d'instance doit savoir à quelle instance attribuer, et c'est pourquoi elle a besoin de self.
.
Prenons une classe de vecteurs simple:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
Nous voulons avoir une méthode qui calcule la longueur. À quoi cela ressemblerait-il si nous voulions le définir à l'intérieur de la classe?
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
À quoi devrait-il ressembler lorsque nous devions le définir en tant que méthode/fonction globale?
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
Donc, toute la structure reste la même. Comment puis-je en profiter? Si nous supposons un instant que nous n’avions pas écrit de méthode length
pour notre classe Vector
, nous pourrions faire ceci:
Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0
Cela fonctionne car le premier paramètre de length_global
peut être réutilisé comme paramètre self
dans length_new
. Cela ne serait pas possible sans un self
explicite.
Une autre façon de comprendre la nécessité de la variable explicite self
consiste à voir où Python ajoute un sucre syntaxique. Lorsque vous gardez à l'esprit que, fondamentalement, un appel comme
v_instance.length()
est transformé en interne pour
Vector.length(v_instance)
il est facile de voir où se situe self
. Vous n'écrivez pas réellement de méthodes d'instance en Python; ce que vous écrivez, ce sont des méthodes de classe qui doivent prendre une instance comme premier paramètre. Et par conséquent, vous devrez placer le paramètre d'instance quelque part explicitement.
Supposons que vous avez une classe ClassA
qui contient une méthode methodA
définie comme suit:
def methodA(self, arg1, arg2):
# do something
et ObjectA
est une instance de cette classe.
Désormais, lorsque ObjectA.methodA(arg1, arg2)
est appelée, python le convertit en interne pour vous en tant que:
ClassA.methodA(ObjectA, arg1, arg2)
La variable self
fait référence à l'objet lui-même.
Lorsque les objets sont instanciés, l'objet lui-même est passé dans le paramètre self.
De ce fait, les données de l’objet sont liées à l’objet. Vous trouverez ci-dessous un exemple de la manière dont vous pourriez visualiser les données de chaque objet. Notez comment ‘self’ est remplacé par le nom de l’objet. Je ne dis pas que cet exemple de diagramme ci-dessous est tout à fait exact, mais il espère qu’il servira un but dans la visualisation de l’utilisation de soi.
L'objet est passé dans le paramètre self afin que l'objet puisse conserver ses propres données.
Bien que cela puisse ne pas être tout à fait exact, songez au processus d’instanciation d’un objet de la manière suivante: lorsqu’un objet est créé, il utilise la classe comme modèle pour ses propres données et méthodes. Sans passer son propre nom dans le paramètre self, les attributs et les méthodes de la classe resteraient en tant que modèle général et ne seraient pas référencés à (appartiennent à) l'objet. Donc, en passant le nom de l'objet dans le paramètre self, cela signifie que si 100 objets sont instanciés à partir d'une classe, ils peuvent tous garder une trace de leurs propres données et méthodes.
Voir l'illustration ci-dessous:
J'aime cet exemple:
class A:
foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]
class A:
def __init__(self):
self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []
Je vais démontrer avec le code que n'utilise pas de classes:
def state_init(state):
state['field'] = 'init'
def state_add(state, x):
state['field'] += x
def state_mult(state, x):
state['field'] *= x
def state_getField(state):
return state['field']
myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)
print( state_getField(myself) )
#--> 'initaddedinitadded'
Les classes ne sont qu’un moyen d’éviter de passer tout le temps dans cet état (et d’autres jolies choses comme l’initialisation, la composition de classe, les métaclasses rarement nécessaires et la prise en charge de méthodes personnalisées pour remplacer les opérateurs).
Maintenant, démontrons le code ci-dessus en utilisant les machines de classe intégrées python, pour montrer en quoi c'est fondamentalement la même chose.
class State(object):
def __init__(self):
self.field = 'init'
def add(self, x):
self.field += x
def mult(self, x):
self.field *= x
s = State()
s.add('added') # self is implicitly passed in
s.mult(2) # self is implicitly passed in
print( s.field )
[a migré ma réponse d'une question fermée en double]
Les extraits suivants sont extraits de documentation Python sur self :
Comme dans Modula-3, il n’existe aucun raccourci [en Python] pour référencer les membres de l’objet à partir de ses méthodes: la fonction method est déclarée avec un premier argument explicite représentant l’objet, qui est fourni implicitement par l’appel.
Souvent, le premier argument d'une méthode s'appelle self. Ce n'est rien de plus qu'une convention: le nom de soi n'a absolument aucune signification pour Python. Notez cependant qu'en ne suivant pas la convention, votre code sera peut-être moins lisible par les autres programmeurs Python. Il est également concevable qu'un programme de navigateur de classe s'appuie sur une telle convention.
Pour plus d'informations, consultez le tutoriel sur les classes de la documentation Python .
En plus de toutes les autres raisons déjà mentionnées, cela permet un accès plus facile aux méthodes remplacées. vous pouvez appeler Class.some_method(inst)
.
Voici un exemple d’utilité:
class C1(object):
def __init__(self):
print "C1 init"
class C2(C1):
def __init__(self): #overrides C1.__init__
print "C2 init"
C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"
Son utilisation est similaire à l'utilisation du mot clé this
en Java, c’est-à-dire pour donner une référence à l’objet en cours.
Python n'est pas un langage conçu pour la programmation orientée objet contrairement à Java ou C++.
Lorsque vous appelez une méthode statique en Python, vous écrivez simplement une méthode contenant des arguments normaux.
class Animal():
def staticMethod():
print "This is a static method"
Cependant, une méthode objet, qui nécessite de créer une variable, qui est un animal, dans ce cas, nécessite l'auto-argument.
class Animal():
def objectMethod(self):
print "This is an object method which needs an instance of a class"
La méthode self est également utilisée pour faire référence à un champ de variable dans la classe.
class Animal():
#animalName made in constructor
def Animal(self):
self.animalName = "";
def getAnimalName(self):
return self.animalName
Dans ce cas, self fait référence à la variable animalName de la classe entière. N'OUBLIEZ PAS: Si vous avez une variable dans une méthode, self ne fonctionnera pas. Cette variable n'existe simplement que pendant l'exécution de cette méthode. Pour définir des champs (les variables de la classe entière), vous devez les définir EN DEHORS des méthodes de classe.
Si vous ne comprenez pas un seul mot de ce que je dis, alors Google "Programmation Orientée Objet". Une fois que vous avez compris cela, vous n’aurez même plus besoin de poser cette question :).
C’est là pour suivre le Python zen "explicite vaut mieux que implicite". Il s’agit bien d’une référence à votre objet de classe. Dans Java et PHP, par exemple, il s'appelle this
.
Si user_type_name
est un champ de votre modèle, vous y accédez par self.user_type_name
.
Tout d'abord, self est un nom conventionnel, vous pouvez mettre n'importe quoi d'autre (être cohérent) à sa place.
Il fait référence à l'objet lui-même. Par conséquent, lorsque vous l'utilisez, vous déclarez que .name et .age sont des propriétés des objets Student (notez, pas de la classe Student) que vous allez créer.
class Student:
#called each time you create a new Student instance
def __init__(self,name,age): #special method to initialize
self.name=name
self.age=age
def __str__(self): #special method called for example when you use print
return "Student %s is %s years old" %(self.name,self.age)
def call(self, msg): #silly example for custom method
return ("Hey, %s! "+msg) %self.name
#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)
#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self
#you can modify attributes, like when alice ages
alice.age=20
print alice
self
est une référence d'objet à l'objet lui-même, donc, ils sont identiques. Les méthodes Python ne sont pas appelées dans le contexte de l'objet lui-même. self
dans Python peut être utilisé pour traiter des modèles d'objet personnalisés ou quelque chose de ce genre.
L'utilisation de l'argument, appelé conventionnellement self
n'est pas aussi difficile à comprendre, mais pourquoi est-ce nécessaire? Ou quant à pourquoi explicitement le mentionner? Je suppose que c'est une question plus importante pour la plupart des utilisateurs qui consultent cette question, ou si ce n'est pas le cas, ils auront certainement la même question à mesure qu'ils avancent dans l'apprentissage du python. Je leur recommande de lire ces quelques blogs:
1: Utilisation de soi-même expliqué
Notez que ce n'est pas un mot clé.
Le premier argument de chaque méthode de classe, y compris init, est toujours une référence à l'instance actuelle de la classe. Par convention, cet argument est toujours nommé self. Dans la méthode init, self fait référence à l'objet nouvellement créé; dans d'autres méthodes de classe, il fait référence à l'instance dont la méthode a été appelée. Par exemple, le code ci-dessous est le même que le code ci-dessus.
Une autre chose que je voudrais ajouter est qu'un argument optionnel self
me permet de déclarer des méthodes statiques dans une classe, en n'écrivant pas self
.
Exemples de code:
class MyClass():
def staticMethod():
print "This is a static method"
def objectMethod(self):
print "This is an object method which needs an instance of a class, and that is what self refers to"
PS: Ceci ne fonctionne que dans Python 3.x.
Dans les versions précédentes, vous devez explicitement ajouter @staticmethod
decorator, sinon l'argument self
est obligatoire.
Je suis surpris que personne n'ait parlé de Lua. Lua utilise également la variable 'self', mais elle peut être omise mais toujours utilisée. C++ fait la même chose avec 'this'. Je ne vois aucune raison de devoir déclarer 'self' dans chaque fonction, mais vous devriez toujours pouvoir l'utiliser comme vous pouvez le faire avec Lua et C++. Pour un langage qui se targue d'être bref, il est étrange qu'il vous oblige à déclarer la variable self.
C’est parce que, en passant, python est conçu, les alternatives ne fonctionneraient guère. Python est conçu pour permettre de définir des méthodes ou des fonctions dans un contexte où this
implicite (a-la Java/C++) ou explicite @
(a-la Ruby) serait non ça marche pas. Prenons un exemple avec l'approche explicite avec les conventions python:
def fubar(x):
self.x = x
class C:
frob = fubar
Maintenant, la fonction fubar
ne fonctionnerait pas car elle supposerait que self
est une variable globale (et également dans frob
). L'alternative serait d'exécuter des méthodes avec une portée globale remplacée (où self
est l'objet).
L’approche implicite serait
def fubar(x)
myX = x
class C:
frob = fubar
Cela signifierait que myX
serait interprété comme une variable locale dans fubar
(et dans frob
également). Dans ce cas, l’alternative serait d’exécuter des méthodes avec une étendue locale remplacée qui serait conservée entre les appels, mais cela supprimerait la possibilité de recourir à des variables locales.
Cependant, la situation actuelle fonctionne bien:
def fubar(self, x)
self.x = x
class C:
frob = fubar
ici, lorsqu'elle est appelée en tant que méthode, frob
recevra l'objet sur lequel il est appelé via le paramètre self
, et fubar
peut toujours être appelé avec un objet en paramètre et fonctionne de la même manière (il - est identique à C.frob
je pense).
Jetez un oeil à l'exemple suivant, qui explique clairement le but de self
class Restaurant(object):
bankrupt = False
def open_branch(self):
if not self.bankrupt:
print("branch opened")
#create instance1
>>> x = Restaurant()
>>> x.bankrupt
False
#create instance2
>>> y = Restaurant()
>>> y.bankrupt = True
>>> y.bankrupt
True
>>> x.bankrupt
False
self
est utilisé/nécessaire pour distinguer les instances.
Dans la méthode __init__
, self fait référence à l'objet nouvellement créé; dans d'autres méthodes de classe, il fait référence à l'instance dont la méthode a été appelée.
self, en tant que nom, est juste une convention , appelez-la comme vous voulez! mais lorsque vous l'utilisez, par exemple pour supprimer l'objet, vous devez utiliser le même nom: __del__(var)
, où var
a été utilisé dans la __init__(var,[...])
.
Vous devriez aussi jeter un oeil à cls
, pour avoir l'image plus grande . Ceci post pourrait être utile.
self
est inévitable. Il y avait juste un question devrait self
être implicite ou explicite. Guido van Rossum
a résolu cette question en disant self
doit rester .
self
? Si nous nous en tenions à la programmation fonctionnelle, nous n’aurions pas besoin de self
. Une fois que nous avons entré le OOP Python , nous y trouvons self
.
Voici le cas d'utilisation typique _class C
_ avec la méthode _m1
_
_class C:
def m1(self, arg):
print(self, ' inside')
pass
ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address
_
Ce programme produira:
_<__main__.C object at 0x000002B9D79C6CC0> outside
<__main__.C object at 0x000002B9D79C6CC0> inside
0x2b9d79c6cc0
_
Donc, self
contient l'adresse de mémoire de l'instance de la classe. Le but de self
serait de contenir la référence pour les méthodes d'instance et que nous ayons accès explicite à cette référence.
Notez qu'il existe trois types de méthodes de classe: