Maison > développement back-end > Tutoriel Python > Comprendre l'utilisation de soi en Python

Comprendre l'utilisation de soi en Python

高洛峰
Libérer: 2017-03-03 15:17:26
original
1650 Les gens l'ont consulté

Quand j'ai commencé à apprendre à écrire des classes en Python, j'ai trouvé cela très gênant. Pourquoi est-ce nécessaire lors de la définition mais pas lors de l'appel ? Pourquoi ne peut-il pas être simplifié en interne pour réduire le nombre de frappes que nous devons effectuer ? ? Vous comprendrez tous vos doutes après avoir lu cet article.

self représente une instance d'une classe, pas une classe.

Exemple pour illustrer :

class Test:
  def prt(self):
    print(self)
    print(self.__class__)
 
t = Test()
t.prt()
Copier après la connexion

Les résultats d'exécution sont les suivants

<__main__.Test object at 0x000000000284E080>
<class &#39;__main__.Test&#39;>
Copier après la connexion

D'après l'exemple ci-dessus, il est évident que self représente une instance d'une classe. Et self.class pointe vers la classe.

self n'a pas besoin d'être écrit comme self

De nombreux enfants apprennent d'abord d'autres langues, puis apprennent Python, donc ils ont toujours l'impression que self est bizarre si. tu veux l'écrire comme ça, tu peux ?

Bien sûr, réécrivons le code ci-dessus. Une fois

class Test:
  def prt(this):
    print(this)
    print(this.__class__)
 
t = Test()
t.prt()
Copier après la connexion

remplacé par ceci, les résultats d'exécution sont exactement les mêmes.

Bien sûr, il est préférable de respecter les habitudes établies et de se servir de soi.

Puis-je ne pas m'écrire ?

Dans l'interpréteur Python, lorsque nous appelons t.prt(), Python l'interprète en fait comme Test.prt(t ), c'est-à-dire remplacer self par une instance de la classe.

Les enfants intéressés peuvent réécrire la ligne t.prt() ci-dessus, et les résultats réels après l'exécution seront exactement les mêmes.

En fait, il a été partiellement expliqué que le soi ne peut pas être omis lors de la définition. Si vous devez l'essayer, veuillez voir ci-dessous :

class Test:
  def prt():
    print(self)
 
t = Test()
t.prt()
Copier après la connexion

.

L'erreur de rappel d'exécution est la suivante : prt n'a pas de paramètres lorsqu'il est défini, mais nous transmettons de force un paramètre lors de son exécution.

Puisque t.prt() est équivalent à Test.prt(t) comme expliqué ci-dessus, le programme nous rappelle que nous avons passé un paramètre t supplémentaire.

Traceback (most recent call last):
 File "h.py", line 6, in <module>
  t.prt()
TypeError: prt() takes 0 positional arguments but 1 was given
Copier après la connexion

Bien sûr, ce n'est pas grave si nous ne transmettons pas une instance de classe lorsque nous la définissons et l'appelons, c'est une méthode de classe.

class Test:
  def prt():
    print(__class__)
Test.prt()
Copier après la connexion

Les résultats en cours d'exécution sont les suivants

<class &#39;__main__.Test&#39;>
Copier après la connexion

En cas d'héritage , pass L'instance saisie est l'instance transmise, et non l'instance de la classe dans laquelle self est défini.

Regardez d'abord le code

class Parent:
  def pprt(self):
    print(self)
 
class Child(Parent):
  def cprt(self):
    print(self)
c = Child()
c.cprt()
c.pprt()
p = Parent()
p.pprt()
Copier après la connexion

Les résultats d'exécution sont les suivants

<__main__.Child object at 0x0000000002A47080>
<__main__.Child object at 0x0000000002A47080>
<__main__.Parent object at 0x0000000002A47240>
Copier après la connexion

Explication :

Il ne devrait y avoir aucun problème de compréhension lors de l'exécution de c.cprt(), qui fait référence à une instance de la classe Child.

Mais lors de l'exécution de c.pprt(), c'est équivalent à Child.pprt(c), donc self fait toujours référence à une instance de la classe Child Puisque la méthode pprt() n'est pas définie dans self, l'héritage est hérité En parcourant l'arborescence, nous constatons que la méthode pprt() est définie dans la classe parent Parent, elle sera donc appelée avec succès.

Dans la classe descripteur, self fait référence à l'instance de la classe descripteur

n'est pas facile à comprendre. Regardons d'abord l'exemple :

<. 🎜>

class Desc:
  def __get__(self, ins, cls):
    print(&#39;self in Desc: %s &#39; % self )
    print(self, ins, cls)
class Test:
  x = Desc()
  def prt(self):
    print(&#39;self in Test: %s&#39; % self)
t = Test()
t.prt()
t.x
Copier après la connexion

Les résultats en course à pied sont les suivants :

self in Test: <__main__.Test object at 0x0000000002A570B8>
self in Desc: <__main__.Desc object at 0x000000000283E208>
<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8> <class &#39;__main__.Test&#39;>
Copier après la connexion

La plupart des chaussures pour enfants démarrent pour avoir des questions, pourquoi sont-elles dans la catégorie Desc ? Le soi défini dans ne devrait-il pas être l'instance t qui l'appelle ? Comment est-il devenu une instance de la classe Desc ?

Remarque : Il faut ouvrir les yeux pour voir clairement ici. Ce qu'on appelle ici est t.x, ce qui signifie que c'est l'attribut x de l'instance t de la classe Test puisque l'attribut x n'est pas défini dans. l'instance t, on trouve l'attribut Class x, et cet attribut est un attribut descripteur, qui est une instance de la classe Desc, il n'y a donc aucune méthode qui utilise Test ici.

Ensuite, si nous appelons l'attribut x directement via la classe, nous pouvons obtenir le même résultat.

Ce qui suit est le résultat du changement de t.x en Test.x.

self in Test: <__main__.Test object at 0x00000000022570B8>
self in Desc: <__main__.Desc object at 0x000000000223E208>
<__main__.Desc object at 0x000000000223E208> None <class &#39;__main__.Test&#39;>
Copier après la connexion

Digression : Puisque dans de nombreux cas, la classe de descripteur a encore besoin de savoir qui est l'instance qui appelle le descripteur, donc dans la classe de descripteur, il y a un deuxième paramètre ins, qui est utilisé pour représenter l'instance de classe qui l'appelle, donc quand t. Lors d'un appel à l'aide de Test.x, None est renvoyé car il n'y a pas d'instance.

Comprendre soi-même en python à partir de l'essence de OO
Par exemple, supposons que je veuille opérer sur les données de l'utilisateur, qui contiennent le nom et l'âge. Si une approche orientée processus est utilisée, l'implémentation ressemblera à ceci.

def user_init(user,name,age): 
  user[&#39;name&#39;] = name 
  user[&#39;age&#39;] = age 
 
def set_user_name(user, x): 
  user[&#39;name&#39;] = x 
 
def set_user_age(user, x): 
  user[&#39;age&#39;] = x 
 
def get_user_name(user): 
  return user[&#39;name&#39;] 
 
def get_user_age(user): 
  return user[&#39;age&#39;] 
 
myself = {} 
user_init(myself,&#39;kzc&#39;,17) 
print get_user_age(myself) 
set_user_age(myself,20) 
print get_user_age(myself)
Copier après la connexion

Comme vous pouvez le constater, les paramètres utilisateur doivent être transmis pour diverses opérations sur l'utilisateur.

Si vous utilisez l'orientation objet, vous n'avez pas besoin de transmettre le paramètre utilisateur à chaque fois. Les données et les opérations pertinentes sont liées au même endroit. Les données peuvent être facilement obtenues à partir de différents endroits de cette classe.
La raison pour laquelle les données sont accessibles à partir de différents endroits de la classe est qu'elles sont liées à self. Bien sûr, le premier paramètre de sa méthode n'a pas besoin d'être appelé self, mais peut être appelé un autre nom. juste une convention.
Ce qui suit est l'implémentation orientée objet. Comme vous pouvez le voir, elle est beaucoup plus structurée, claire et lisible.

class User(object): 
  def __init__(self,name,age): 
    self.name = name 
    self.age = age 
 
  def SetName(self,name): 
    self.name = name 
 
  def SetAge(self,age): 
    self.age = age 
 
  def GetName(self): 
    return self.name 
 
  def GetAge(self): 
    return self.age 
 
u = User(&#39;kzc&#39;,17) 
print u.GetName() 
print u.GetAge()
Copier après la connexion

Comme vous pouvez le voir dans l'exemple ci-dessus, l'orientation objet est en fait très utile, mais la plupart des gens ne l'absorbent pas bien et ne l'encapsulent pas eh bien, application incorrecte.

Résumé

  • Self doit être défini lors de la définition, mais il sera automatiquement transmis lors de l'appel.

  • Le nom de soi n'est pas fixe, mais il est préférable d'utiliser soi

    selon l'accord

  • self fait toujours référence à l'instance de la classe lorsqu'elle est appelée.

Pour plus d'articles sur la compréhension de l'utilisation de self en Python, veuillez faire attention au site Web PHP chinois !


Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal