Par ce que vous avez écrit, il vous manque un élément essentiel de compréhension: la différence entre une classe et un objet. __init__
n'initialise pas une classe, il initialise une instance d'une classe ou d'un objet. Chaque chien a une couleur, mais pas les chiens en tant que classe. Chaque chien a quatre pieds ou moins, mais pas la classe des chiens. La classe est un concept d'objet. Quand vous voyez Fido et Spot, vous reconnaissez leur similitude, leur dogness. Voilà la classe.
Quand tu dis
class Dog:
def __init__(self, legs, colour):
self.legs = legs
self.colour = colour
fido = Dog(4, "brown")
spot = Dog(3, "mostly yellow")
Vous dites que Fido est un chien brun avec 4 pattes tandis que Spot est un peu infirme et est principalement jaune. La __init__
fonction s'appelle un constructeur, ou initialiseur, et est automatiquement appelée lorsque vous créez une nouvelle instance d'une classe. Dans cette fonction, l'objet nouvellement créé est affecté au paramètre self
. La notation self.legs
est un attribut appelé legs
de l'objet dans la variable self
. Les attributs sont un peu comme des variables, mais ils décrivent l'état d'un objet, ou des actions (fonctions) particulières disponibles pour l'objet.
Cependant, notez que vous ne vous fixez pas colour
pour la doghood elle-même - c'est un concept abstrait. Il y a des attributs qui ont du sens sur les classes. Par exemple, en population_size
est un - cela n'a pas de sens de compter le Fido parce que Fido en est toujours un. Il est logique de compter les chiens. Disons qu'il y a 200 millions de chiens dans le monde. C'est la propriété de la classe Dog. Fido n'a rien à voir avec le nombre de 200 millions, ni Spot. C'est ce qu'on appelle un "attribut de classe", par opposition aux "attributs d'instance" qui sont colour
ou legs
plus.
Maintenant, à quelque chose de moins canin et de plus lié à la programmation. Comme j'écris ci-dessous, la classe pour ajouter des choses n'est pas raisonnable - de quoi s'agit-il? Les classes en Python sont constituées de collections de données différentes, qui se comportent de la même manière. La classe de chiens comprend Fido et Spot et 199999999998 autres animaux similaires à eux, tous urinant sur les lampadaires. En quoi consiste la classe pour ajouter des choses? Par quelles données inhérentes à eux diffèrent-ils? Et quelles actions partagent-ils?
Cependant, les chiffres ... ce sont des sujets plus intéressants. Dites, les nombres entiers. Il y en a beaucoup, beaucoup plus que des chiens. Je sais que Python a déjà des nombres entiers, mais jouons à l'idiot et les "implémentons" à nouveau (en trichant et en utilisant les entiers de Python).
Ainsi, les nombres entiers sont une classe. Ils ont des données (valeur), et certains comportements ("ajoutez-moi à cet autre nombre"). Montrons ceci:
class MyInteger:
def __init__(self, newvalue)
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
def add(self, other):
# when an integer wants to add itself to another integer,
# we'll take their values and add them together,
# then make a new integer with the result value.
return MyInteger(self.value + other.value)
three = MyInteger(3)
# three now contains an object of class MyInteger
# three.value is now 3
five = MyInteger(5)
# five now contains an object of class MyInteger
# five.value is now 5
eight = three.add(five)
# here, we invoked the three's behaviour of adding another integer
# now, eight.value is three.value + five.value = 3 + 5 = 8
print eight.value
# ==> 8
C'est un peu fragile (nous supposons que ce other
sera un MyInteger), mais nous l'ignorerons maintenant. Dans le vrai code, nous ne le ferions pas; nous le testerions pour nous en assurer, et peut-être même le forcerons ("vous n'êtes pas un entier? par golly, vous avez 10 nanosecondes pour en devenir un! 9 ... 8 ....")
On pourrait même définir des fractions. Les fractions savent également comment s'additionner.
class MyFraction:
def __init__(self, newnumerator, newdenominator)
self.numerator = newnumerator
self.denominator = newdenominator
# because every fraction is described by these two things
def add(self, other):
newdenominator = self.denominator * other.denominator
newnumerator = self.numerator * other.denominator + self.denominator * other.numerator
return MyFraction(newnumerator, newdenominator)
Il y a encore plus de fractions que d'entiers (pas vraiment, mais les ordinateurs ne le savent pas). Faisons deux:
half = MyFraction(1, 2)
third = MyFraction(1, 3)
five_sixths = half.add(third)
print five_sixths.numerator
# ==> 5
print five_sixths.denominator
# ==> 6
Vous ne déclarez rien ici. Les attributs sont comme un nouveau type de variable. Les variables normales n'ont qu'une seule valeur. Disons que vous écrivez colour = "grey"
. Vous ne pouvez pas avoir une autre variable nommée colour
qui n'est "fuchsia"
pas au même endroit dans le code.
Les tableaux résolvent cela dans une certaine mesure. Si vous dites colour = ["grey", "fuchsia"]
, vous avez empilé deux couleurs dans la variable, mais vous les distinguez par leur position (0 ou 1, dans ce cas).
Les attributs sont des variables liées à un objet. Comme avec les tableaux, nous pouvons avoir beaucoup de colour
variables, sur différents chiens . Donc, fido.colour
est une variable, mais spot.colour
est une autre. Le premier est lié à l'objet dans la variable fido
; le second spot
,. Maintenant, quand tu appellesDog(4, "brown")
, ou three.add(five)
, il y aura toujours un paramètre invisible, qui sera assigné au paramètre supplémentaire pendant au début de la liste de paramètres. Il est appelé conventionnellement self
et obtiendra la valeur de l'objet devant le point. Ainsi, dans le __init__
(constructeur) du Chien , self
sera ce que le nouveau Chien se révélera être; dans MyInteger
's add
, self
sera lié à l'objet dans la variable three
. Donc,three.value
sera la même variable en dehors du add
, que self.value
dans le add
.
Si je dis the_mangy_one = fido
, je commencerai à faire référence à l'objet connu sous fido
un autre nom. Désormais, fido.colour
c'est exactement la même variable que the_mangy_one.colour
.
Alors, les choses à l'intérieur du __init__
. Vous pouvez les considérer comme notant des choses dans le certificat de naissance du chien. colour
en soi est une variable aléatoire, peut contenir n'importe quoi. fido.colour
ou self.colour
est comme un champ de formulaire sur la feuille d'identité du chien; et __init__
le greffier le remplit-il pour la première fois.
Un plus clair?
EDIT : développer le commentaire ci-dessous:
Vous voulez dire une liste de objets , n'est-ce pas?
Tout d'abord, ce fido
n'est en fait pas un objet. C'est une variable, qui contient actuellement un objet, tout comme quand vous dites x = 5
, x
est une variable contenant actuellement le nombre cinq. Si vous changez d'avis plus tard, vous pouvez le faire fido = Cat(4, "pleasing")
(tant que vous avez créé une classeCat
), et à fido
partir de ce moment-là «contiendra» un objet chat. Si vous le faites fido = x
, il contiendra alors le numéro cinq, et pas du tout un objet animal.
Une classe en elle-même ne connaît pas ses instances à moins que vous n'écriviez spécifiquement du code pour en garder une trace. Par exemple:
class Cat:
census = [] #define census array
def __init__(self, legs, colour):
self.colour = colour
self.legs = legs
Cat.census.append(self)
Voici census
un attribut de Cat
classe au niveau de la classe.
fluffy = Cat(4, "white")
spark = Cat(4, "fiery")
Cat.census
# ==> [<__main__.Cat instance at 0x108982cb0>, <__main__.Cat instance at 0x108982e18>]
# or something like that
Notez que vous n'obtiendrez pas [fluffy, sparky]
. Ce ne sont que des noms variables. Si vous voulez que les chats eux-mêmes aient des noms, vous devez créer un attribut distinct pour le nom, puis remplacer la __str__
méthode pour renvoyer ce nom. Le but de cette méthode (c'est-à-dire la fonction liée à une classe, tout comme add
ou __init__
) est de décrire comment convertir l'objet en chaîne, comme lorsque vous l'imprimez.