web-dev-qa-db-fra.com

Quel est le but de la Parole 'self', en Python?

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).

1028
richzilla

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..

662
Thomas Wouters

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.

406
Debilski

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.

353
Arjun Sreedharan

Lorsque les objets sont instanciés, l'objet lui-même est passé dans le paramètre self.

enter image description here

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.

enter image description here

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:

enter image description here

197
sw123456

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: []
74
kame

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]

36
ninjagecko

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 .

18
Matthew Rankin

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"
18
Ponkadoodle

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.

14
Gaurav Nishant

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 :).

12
ytpillai

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.

8
dan-klasson

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

Le code est ici

6
Akash Kandpal

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.

6
Ming-Tang

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.

2: Pourquoi l'avons-nous ainsi et pourquoi ne pouvons-nous pas l'éliminer comme argument, comme en Java, et avoir un mot clé à la place

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.

5
Bugs Buggy

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.

5
user441521

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).

4
skyking

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.

4
kmario23

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.

2
TheEnglishMe

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 .

Alors, où habite la 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:

  • méthodes statiques (lire: fonctions),
  • méthodes de classe,
  • méthodes d'instance (mentionnées).
0
prosti