Question Quel est le but de soi?


Quel est le but de la self mot 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, dans Ruby je peux faire ceci:

class myClass
    def myFunc(name)
        @name = name
    end
end

Ce que je comprends, assez facilement. Cependant, en Python, j'ai besoin d'inclure self:

class myClass:
    def myFunc(self, name):
        self.name = name

Quelqu'un peut-il me parler à travers cela? Ce n'est pas quelque chose que j'ai rencontré dans mon expérience (certes limitée).


883
2018-04-25 20:22


origine


Réponses:


La raison pour laquelle vous devez utiliser self. est parce que Python n'utilise pas le @ 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é automatiquement, mais pas reçu automatiquement: le premier paramètre des méthodes est l'instance sur laquelle la méthode est appelée. Cela rend les méthodes entièrement identiques aux fonctions, et laisse le nom à utiliser jusqu'à vous (bien que self est la convention, et les gens vont généralement froncer les sourcils à vous quand vous utilisez quelque chose d'autre.) self n'est pas spécial au code, c'est juste un autre objet.

Python aurait pu faire autre chose pour distinguer les noms normaux des attributs - syntaxe spéciale comme Ruby, ou nécessitant des déclarations comme C ++ et Java, ou peut-être quelque chose de plus différent - mais ce n'est pas le cas. Python est tout pour rendre les choses explicites, ce qui rend é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'affectation à un attribut d'instance doit savoir à quelle instance attribuer, et c'est pourquoi il a besoin self..


584
2018-04-25 20:25



Prenons un cours de vecteur 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 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)

A quoi devrait-il ressembler quand nous devions le définir comme une 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 m'en servir? Si nous supposons pour un moment que nous n'avions pas écrit un length méthode pour notre Vector classe, nous pourrions le faire:

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0

Cela fonctionne parce que le premier paramètre de length_global, peut être réutilisé comme self paramètre dans length_new. Cela ne serait pas possible sans un self.


Une autre façon de comprendre le besoin de l'explicite self est de voir où Python ajoute du sucre syntaxique. Quand vous gardez à l'esprit, que, fondamentalement, un appel comme

v_instance.length()

est transformé en interne à

Vector.length(v_instance)

il est facile de voir où le self s'inscrit. Vous n'écrivez pas de méthodes d'instance en Python; ce que vous écrivez est des méthodes de classe qui doivent prendre une instance comme premier paramètre. Et donc, vous devrez placer le paramètre d'instance quelque part explicitement.


382
2018-04-28 00:03



Disons que vous avez une classe ClassA qui contient une méthode methodA défini comme:

def methodA(self, arg1, arg2):
    # do something

et ObjectA est une instance de cette classe.

Maintenant, quand ObjectA.methodA(arg1, arg2) est appelé, python le convertit en interne pour vous:

ClassA.methodA(ObjectA, arg1, arg2)

le self La variable fait référence à l'objet lui-même.


283
2018-01-26 17:31



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

enter image description here

Pour cette raison, les données de l'objet sont liées à l'objet. Voici un exemple de la façon dont vous aimeriez visualiser les données de chaque objet. Remarquez comment 'self' est remplacé par le nom de l'objet. Je ne dis pas que ce diagramme d'exemple ci-dessous est tout à fait exact mais il espère avec servir à 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 ne soit pas tout à fait exact, pensez au processus d'instanciation d'un objet comme celui-ci: 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 méthodes de la classe resteraient comme un modèle général et ne seraient pas référencés à (appartenir à) l'objet. Ainsi, en passant le nom de l'objet dans le paramètre self, cela signifie que si 100 objets sont instanciés à partir de la classe, ils peuvent tous garder une trace de leurs propres données et méthodes.

Voir l'illustration ci-dessous:

enter image description here


151
2018-06-28 05:47



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

65
2018-04-26 16:02



Je vais démontrer avec le code que n'utilise pas les 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 sont juste un moyen d'éviter de passer tout le temps dans cet état (et d'autres choses intéressantes comme l'initialisation, la composition de classes, les métaclasses rarement nécessaires et le support de méthodes personnalisées pour remplacer les opérateurs).

Maintenant, montrons le code ci-dessus en utilisant la machinerie de classe python intégrée, pour montrer comment 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 )

[migré ma réponse à partir de la question fermée en double]


33
2018-06-22 00:27



En plus de toutes les autres raisons déjà mentionnées, cela permet un accès plus facile aux méthodes surchargées; tu peux appeler Class.some_method(inst).

Un exemple d'où c'est utile:

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"

17
2018-04-25 20:31



Les extraits suivants proviennent du Documentation Python sur soi:

Comme dans Modula-3, il n'y a pas de 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, 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 self n'a absolument aucune signification particulière pour Python. Notez cependant qu'en ne suivant pas la convention, votre code peut être moins lisible par d'autres programmeurs Python, et il est également concevable qu'un programme de navigateur de classe puisse être écrit sur la base d'une telle convention.

Pour plus d'informations, voir Didacticiel de documentation Python sur les classes.


16
2018-04-25 20:29



Python n'est pas un langage construit 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 avec des arguments réguliers à l'intérieur.

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, a besoin de l'argument self

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 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. RAPPELEZ-VOUS: Si vous avez une variable dans une méthode, l'auto ne fonctionnera pas. Cette variable n'existe simplement que lorsque cette méthode est en cours d'exécution. Pour définir les champs (les variables de la classe entière), vous devez les définir en dehors des méthodes de la classe.

Si vous ne comprenez pas un seul mot de ce que je dis, alors Google "Object Oriented Programming". Une fois que vous aurez compris cela, vous n'aurez même pas besoin de poser cette question :).


11
2018-05-25 16:04