Object Oriented Programming - Attributes and Methods in Classes
Intro
Dans la quête précédente, on a vu :
- ce qu'est une Class (classe, le plan qui décrit un type d'objet),
- la différence entre les Classes et les Objects (objets, les exemplaires créés à partir d'une classe),
- ce qu'est
selfet la méthode constructeur (constructor, la méthode qui initialise l'objet).
Content
✅ À la fin de cette quête, tu sauras écrire et lire des classes.
Avant de continuer, assure-toi que tous les sujets abordés dans la quête précédente sont clairs pour toi.
On continue avec l'exemple du chat Tamagotchi qu'on a commencé dans la quête précédente.
Ajouter des attributs
Maintenant qu'on a la structure de départ de la classe, définissons les attributs.
Les attributes (attributs) sont un groupe de variables qui décrivent les caractéristiques importantes du sujet sur lequel tu te concentres (ta Class). Dans l'exemple du chat, quand on crée une classe pour les chats, on peut vouloir suivre leur niveau de fatigue (s'ils sont fatigués), leur niveau de faim (à quel point ils ont faim), leur niveau de santé (à quel point ils sont en bonne santé).
Chacune de ces valeurs est enregistrée dans des variables à l'intérieur de la classe. On les appelle des attributes.
Astuce : quand tu construis une Class, note chaque information que tu veux connaître sur le sujet principal (qui doit être ta Class). Ce seront tes attributs.
Maintenant, définissons les attributs de notre classe. Ils sont en général initialisés dans le constructeur, soit avec des valeurs par défaut, soit via les paramètres de la méthode constructeur.
class Cat:
def __init__(self, name):
## Let's add all the variables we want to know about the cat
## Values can be filled at initialization or default
self.name = name # example of variable filled during initialization
self.sleepiness = 0 # This could be a boolean or a value from 0 to 9
self.hunger = 0 # This could be a boolean or a value from 0 to 9
self.cold = 0
self.playfulness = 10 # Could also be thought as energy
self.health = 10
Dans ce cas, notre objet peut être initialisé de la même manière qu'avant. Lance la ligne suivante pour initialiser l'objet.
captain_meow = Cat('Captain Meow')
captain_meow.cold # This line will give you the level of cold YOUR cat (the object) is feeling at the moment
Ces attributs peuvent être fixés à l'initialisation (comme la plupart dans l'exemple précédent) ou recevoir des valeurs pendant l'initialisation, comme dans l'exemple suivant :
class Cat:
def __init__(self, name, sleepy, hungry, cold, playfulness, health):
## We will set all the attributes to be filled during initialization
self.name = name # example of variable filled during initialization
self.sleepiness = sleepy # This could be a boolean or a value from 0 to 9
self.hunger = hungry # This could be a boolean or a value from 0 to 9
self.cold = cold
self.playfulness = playfulness # Could also be thought as energy
self.health = health
Tu arrives à repérer toutes les différences ?
Click to reveal|||text||||||0|||Hide|||
All the previous fixed variables are now passed as method parameters.
Maintenant, on aimerait obtenir le même résultat qu'avant, quand tous ces attributs étaient fixés. À quoi ressemblerait notre fonction d'initialisation de l'objet ?
Click to reveal|||python||||||0|||Hide|||
captain_meow = Cat('Captain Meow', 0, 0, 0, 10, 10)
captain_meow.cold # Compare the results. Are they the same? Why?
Excellent travail !!
true
# Remarque que `self` n'est jamais mentionné pendant l'initialisation de l'objet. Pourquoi ?
[] On l'a oublié.
[x] Parce qu'il fait référence à l'objet lui-même. C'est un attribut interne.
Maintenant, appelons les attributs de l'objet. Lance le code suivant :
print(f"How sleepy is {captain_meow.name}? {captain_meow.sleepiness}")
Remarque que, à l'intérieur de la classe, on écrit self.sleepiness, car self fait référence à n'importe quelle instance (instance, un exemplaire concret de la classe) avec laquelle la méthode est utilisée. Ici, on utilise un objet précis créé à partir de la classe, donc on appelle le nom de cet objet précis, et non self, pour accéder à ses propres attributs.
Maintenant, on sait initialiser et afficher les états internes des classes (aussi appelés attributes). Mais comment les modifier ?
Ajouter des méthodes
Maintenant qu'on en sait un peu plus sur les variables qu'on veut connaître sur notre chat, on doit ajouter quelques méthodes supplémentaires pour nous aider à changer la valeur des attributs. Les méthodes qu'on peut appeler « depuis l'extérieur de la classe » s'appellent des explicit methods (méthodes explicites). Ce sont les méthodes qu'on va écrire maintenant, pour que notre chat puisse faire quelque chose. Pour cet exemple, on continue avec la version où on définit tous les attributs au moment où on initialise l'objet.
La façon d'initialiser une méthode est simple : il suffit d'écrire la fonction à l'intérieur de la Class, en faisant référence aux attributs avec self. Si tu veux manipuler un des attributs dans la méthode, mets self comme premier paramètre d'entrée. Pour le reste, rien de nouveau, on connaît déjà bien les fonctions maintenant 😊
Maintenant, écrivons quelques actions que notre chat peut faire !
class Cat():
# This is the constructor we previously saw
def __init__(self, name, sleepy, hungry, cold, playfulness, health):
## Let's add all the cat can be
self.name = name # example of variable filled during initialization
self.sleepiness = sleepy # This could be a boolean or a value from 0 to 9
self.hunger = hungry # This could be a boolean or a value from 0 to 9
self.cold = cold
self.playfulness = playfulness # Could also be thought as energy
self.health = health
## Now let's add all the actions the cat can take
def sleeps(self):
# The cats sleeps for 8 hours straight each time, gains one health point and one hunger point each time and the total amount of playfulness points
self.sleepiness = 0
self.playfulness = 10
self.health += 1 if self.health < 10 else 0
self.hunger += 1 if self.hunger < 10 else 0
print(f"The cat {self.name} has slept!")
def plays_inside(self, mins_of_play = 30):
# The cat gets sleepier by each 10 minutes of play and loses all of its playfulness on the same hour
self.playfulness = (self.playfulness - int(mins_of_play /10)) if mins_of_play < 60 else 0 # normal use of ternary function
self.sleepiness = (self.sleepiness + int(mins_of_play /10)) if mins_of_play < 60 else 10
print(f"The cat {self.name} has played for {mins_of_play} minutes inside the house.")
def eats(self, spoons_of_tuna = 2):
# The cat loses the hunger after it eats 5 spoons of tuna, gets one more point more playful each 4 spoons of tuna
self.hunger = (self.hunger - spoons_of_tuna * 2) if spoons_of_tuna < 5 else 0
self.playfulness = (self.playfulness + int(spoons_of_tuna / 4)) if self.playfulness < 10 else 10
print(f"The cat {self.name} has eaten {spoons_of_tuna} spoons of tuna. Yum!")
Remarque que dans la première méthode qu'on a initialisée, il n'y a pas d'autre paramètre que self, alors que dans les autres il y a plusieurs paramètres supplémentaires. Même si ce n'est pas le cas ici, il existe aussi des situations où les méthodes n'ont aucun paramètre d'entrée. Selon les cas, les méthodes qu'on appelle doivent correspondre à la définition écrite dans la Class.
Appelons les méthodes
Voyons comment utiliser notre classe de chat. Pour utiliser le code suivant, tu dois d'abord lancer le code précédent sur la définition de la classe.
Pour utiliser les méthodes d'une classe, on structure le code de cette façon :
object_name.method(additional_input_parameters)
Avec cette structure, on peut écrire (et lancer) le code suivant :
# First run the previous code block, otherwise the interpreter won't know which class we are talking about
# Now run the following code:
captain_meow = Cat('Captain Meow', 0, 0, 0, 10, 10) # Are we using the class we initialized with the default variable?
print(f"\n{captain_meow.name} is alive. Here are the following attributes' value")
#Let's check the attributes
print('\n\nAfter initialization:')
print(f"How sleepy is {captain_meow.name} now? {captain_meow.sleepiness}")
print(f"How hungry is {captain_meow.name} now? {captain_meow.hunger}")
print(f"How cold is {captain_meow.name} now? {captain_meow.cold}")
print(f"How playful is {captain_meow.name} now? {captain_meow.playfulness}")
print(f"How healthy is {captain_meow.name} now? {captain_meow.health}")
# Now let's have our cat play for a bit and ask again:
captain_meow.plays_inside(90) # In this case our additional input parameter is the amount of minutes of play, we just let our cat play for an hour and a half
#Let's check the attributes
print('\n\nAfter play:')
print(f"How sleepy is {captain_meow.name} now? {captain_meow.sleepiness}")
print(f"How hungry is {captain_meow.name} now? {captain_meow.hunger}")
print(f"How cold is {captain_meow.name} now? {captain_meow.cold}")
print(f"How playful is {captain_meow.name} now? {captain_meow.playfulness}")
print(f"How healthy is {captain_meow.name} now? {captain_meow.health}")
#Now the cat is sleepy, let's make it sleep
captain_meow.sleeps() # In this case there are no additional input parameters
#Let's check the attributes
print('\n\nAfter sleep:')
print(f"How sleepy is {captain_meow.name} now? {captain_meow.sleepiness}")
print(f"How hungry is {captain_meow.name} now? {captain_meow.hunger}")
print(f"How cold is {captain_meow.name} now? {captain_meow.cold}")
print(f"How playful is {captain_meow.name} now? {captain_meow.playfulness}")
print(f"How healthy is {captain_meow.name} now? {captain_meow.health}")
À toi de jouer. Imagine une méthode pour modifier l'attribut cold. Une fois que tu as fini de l'écrire, regarde l'option dans l'onglet caché ci-dessous.
Click to reveal|||python||||||0|||Hide|||
#One option could be
# To be added to the class
def plays_outside(self, mins_of_play = 30):
# In addition to the play_inside changes on the attributes, the play_outside gets one more point of cold and one less in health
self.playful = (self.playfulness - int(time/10)) if mins_of_play < 60 else 0 # normal use of ternary function
self.sleepiness = (self.sleepiness + int(time/10)) if mins_of_play < 60 else 10
self.cold += 1
self.health -= 1 if self.health < 0 else 0
print(f"The cat {self.name} has played outside for {mins_of_play} minutes. Etchi!")
Tu fais vraiment du super boulot. Avant de passer au Challenge, regardons quelques ressources supplémentaires.
Ressources supplémentaires
Pour en savoir un peu plus sur la structure générale des classes, lis ceci.
Vidéo sur les classes Python
Article sur les classes Python
Joue avec un autre exemple
💪 Challenge
Crée ton propre notebook Colab et écris la classe Dog pour le Tamagotchi en utilisant le meilleur de tes connaissances en programmation orientée objet (Object Oriented Programming, la façon de programmer en créant des objets à partir de classes) et en programmation Python.
Pour en créer un, suis les étapes :
- liste 5 variables que tu veux connaître sur ton chien (tu peux mettre cette partie dans une zone de texte ou la commenter dans une zone de code) ;
- liste 5 activités que tu aimerais que ton chien fasse. Pour chaque activité, réfléchis à la façon dont elle influence au moins deux variables du Dog (tu peux mettre cette partie dans une zone de texte ou la commenter dans une zone de code) ;
- construis la classe en initialisant les attributs par défaut ou à l'initialisation, comme bon te semble.
- (Temps de test) initialise un objet et fais passer ton chien par au moins 10 activités (tu dois avoir 10 lignes différentes où tu appelles une méthode), affiche tous les attributs à chaque fois que tu appelles une méthode (assure-toi d'appeler toutes les méthodes que tu as créées) pour vérifier que les attributs sont affectés de la manière voulue.
Critères de validation
- Le fichier lié est accessible à toute personne disposant du lien
- Toutes les missions ont été réalisées
Intro
Last quest we covered:
- what is a Class,
- the difference between Classes and Objects,
- what is
selfand the constructor method.
Content
✅ After this quest, we will be able to write and read classes.
Before proceeding, please make sure all the topics covered in the previous quest are clear for you.
We will continue with the example of the Tamagotchi cat we started in the previous quest.
Adding Attributes
Now that we have the initial structure of the class, let's define the attributes.
The attributes are a group of variables describing important features of the topic you are focusing on (your Class). In the cat example, when we make a class for cats, we might want to track their level of tiredness (whether they are tired), their level of hunger (how much hungry they are), their level of health (how healthy they are).
Each of these values are saved into variables inside the class. They are called attributes.
Tip: when you build a Class, write down every piece of information you want to know about the main topic (which should be your Class). Those will be your attributes.
Now let's define the attributes of our class. They are usually initialized in the constructor, either with default values, or through parameters of the constructor method.
class Cat:
def __init__(self, name):
## Let's add all the variables we want to know about the cat
## Values can be filled at initialization or default
self.name = name # example of variable filled during initialization
self.sleepiness = 0 # This could be a boolean or a value from 0 to 9
self.hunger = 0 # This could be a boolean or a value from 0 to 9
self.cold = 0
self.playfulness = 10 # Could also be thought as energy
self.health = 10
In this case, our object can be initialized the same way as before. Run the following line to initialize the object.
captain_meow = Cat('Captain Meow')
captain_meow.cold # This line will give you the level of cold YOUR cat (the object) is feeling at the moment
This attributes can be fixed at initialization (like most of them in the previous example) or they can get values during the initialization, as in the following example:
class Cat:
def __init__(self, name, sleepy, hungry, cold, playfulness, health):
## We will set all the attributes to be filled during initialization
self.name = name # example of variable filled during initialization
self.sleepiness = sleepy # This could be a boolean or a value from 0 to 9
self.hunger = hungry # This could be a boolean or a value from 0 to 9
self.cold = cold
self.playfulness = playfulness # Could also be thought as energy
self.health = health
Can you spot all the differences?
Click to reveal|||text||||||0|||Hide|||
All the previous fixed variables are now passed as method parameters.
So, now we would like to obtain the same result as before, when all these attributes were fixed. What would our object initialization function look like?
Click to reveal|||python||||||0|||Hide|||
captain_meow = Cat('Captain Meow', 0, 0, 0, 10, 10)
captain_meow.cold # Compare the results. Are they the same? Why?
Awesome work!!
true
# Notice that the self is never mentioned during object initialization. Why is that?
[] We forgot about it.
[x] Because refers to the object itself. It's an internal attribute.
Now let's call the object's attributes. Please run the following code:
print(f"How sleepy is {captain_meow.name}? {captain_meow.sleepiness}")
Notice that when inside the class we write self.sleepiness, as self refers to any instance of the class the method is used with. In this case we are using a specific object created from the class, therefore we are calling the specific object's name, not self, to access its own attributes.
Now we know how to initialize and display the classes' internal states (also known as attributes). But how do we change them?
Adding Methods
Now that we know a bit about the variables we want to know about our cat, we need to add some additional methods to help ourselves change the attributes' value. Methods that can be called from "outside the class" are called explicit methods. These are the methods we are going to write now, so our cat can do something. For this example we will move forward with the version in which we define all the attributes when we initialize the object.
The way to initialize a method is simple: we just need to write the function inside the Class, referring to the attributes using self. If you want to manipulate one of the attributes inside the method, put self as the first input parameter. For the rest there is nothing new, we all know a lot about functions by now 😊
Now let's write some actions for our cat to do!
class Cat():
# This is the constructor we previously saw
def __init__(self, name, sleepy, hungry, cold, playfulness, health):
## Let's add all the cat can be
self.name = name # example of variable filled during initialization
self.sleepiness = sleepy # This could be a boolean or a value from 0 to 9
self.hunger = hungry # This could be a boolean or a value from 0 to 9
self.cold = cold
self.playfulness = playfulness # Could also be thought as energy
self.health = health
## Now let's add all the actions the cat can take
def sleeps(self):
# The cats sleeps for 8 hours straight each time, gains one health point and one hunger point each time and the total amount of playfulness points
self.sleepiness = 0
self.playfulness = 10
self.health += 1 if self.health < 10 else 0
self.hunger += 1 if self.hunger < 10 else 0
print(f"The cat {self.name} has slept!")
def plays_inside(self, mins_of_play = 30):
# The cat gets sleepier by each 10 minutes of play and loses all of its playfulness on the same hour
self.playfulness = (self.playfulness - int(mins_of_play /10)) if mins_of_play < 60 else 0 # normal use of ternary function
self.sleepiness = (self.sleepiness + int(mins_of_play /10)) if mins_of_play < 60 else 10
print(f"The cat {self.name} has played for {mins_of_play} minutes inside the house.")
def eats(self, spoons_of_tuna = 2):
# The cat loses the hunger after it eats 5 spoons of tuna, gets one more point more playful each 4 spoons of tuna
self.hunger = (self.hunger - spoons_of_tuna * 2) if spoons_of_tuna < 5 else 0
self.playfulness = (self.playfulness + int(spoons_of_tuna / 4)) if self.playfulness < 10 else 10
print(f"The cat {self.name} has eaten {spoons_of_tuna} spoons of tuna. Yum!")
Notice that in the first method we initialized, there is no additional parameter than self, in the other ones there are several additional parameters. Although it's not the case here, there are also situations in which methods have no input parameters whatsoever. Depending on the case, we need to have the methods we call, matching the definition written in the Class.
Let's Call the Methods
Let's see how our cat class can be used. To use the following code, you need to run the previous code on the class definition first.
In order to use the methods of a class, we need to structure the code this way:
object_name.method(additional_input_parameters)
Using that structure, we can write (and run) the following code:
# First run the previous code block, otherwise the interpreter won't know which class we are talking about
# Now run the following code:
captain_meow = Cat('Captain Meow', 0, 0, 0, 10, 10) # Are we using the class we initialized with the default variable?
print(f"\n{captain_meow.name} is alive. Here are the following attributes' value")
#Let's check the attributes
print('\n\nAfter initialization:')
print(f"How sleepy is {captain_meow.name} now? {captain_meow.sleepiness}")
print(f"How hungry is {captain_meow.name} now? {captain_meow.hunger}")
print(f"How cold is {captain_meow.name} now? {captain_meow.cold}")
print(f"How playful is {captain_meow.name} now? {captain_meow.playfulness}")
print(f"How healthy is {captain_meow.name} now? {captain_meow.health}")
# Now let's have our cat play for a bit and ask again:
captain_meow.plays_inside(90) # In this case our additional input parameter is the amount of minutes of play, we just let our cat play for an hour and a half
#Let's check the attributes
print('\n\nAfter play:')
print(f"How sleepy is {captain_meow.name} now? {captain_meow.sleepiness}")
print(f"How hungry is {captain_meow.name} now? {captain_meow.hunger}")
print(f"How cold is {captain_meow.name} now? {captain_meow.cold}")
print(f"How playful is {captain_meow.name} now? {captain_meow.playfulness}")
print(f"How healthy is {captain_meow.name} now? {captain_meow.health}")
#Now the cat is sleepy, let's make it sleep
captain_meow.sleeps() # In this case there are no additional input parameters
#Let's check the attributes
print('\n\nAfter sleep:')
print(f"How sleepy is {captain_meow.name} now? {captain_meow.sleepiness}")
print(f"How hungry is {captain_meow.name} now? {captain_meow.hunger}")
print(f"How cold is {captain_meow.name} now? {captain_meow.cold}")
print(f"How playful is {captain_meow.name} now? {captain_meow.playfulness}")
print(f"How healthy is {captain_meow.name} now? {captain_meow.health}")
Now you try. Think of a method to change the cold attribute. After you finish writing it, check the option in the hidden tab below.
Click to reveal|||python||||||0|||Hide|||
#One option could be
# To be added to the class
def plays_outside(self, mins_of_play = 30):
# In addition to the play_inside changes on the attributes, the play_outside gets one more point of cold and one less in health
self.playful = (self.playfulness - int(time/10)) if mins_of_play < 60 else 0 # normal use of ternary function
self.sleepiness = (self.sleepiness + int(time/10)) if mins_of_play < 60 else 10
self.cold += 1
self.health -= 1 if self.health < 0 else 0
print(f"The cat {self.name} has played outside for {mins_of_play} minutes. Etchi!")
You are doing such a great job. Before going to the Challenge, let's check out a couple of additional sources.
Additional Resources
To know a bit more about the general structure of the classes, read this.
Video on Python Classes
Post on Python Classes
Mess around with another example
💪 Challenge
Create your own Colab notebook and write the Dog Class for the Tamagotchi using the best of your knowledge in Object Oriented Programming and Python Programming.
In order to create one, follow the steps:
- list 5 variables you are interested to know about your dog (you can put this part in a text box or comment it in a code box);
- list 5 activities you would like your dog to do. For each activity, consider how the activity influences at least two variables of the Dog (you can put this part in a text box or comment it in a code box);
- build the class initializing the attributes by default or at initialization as you see fit.
- (Test Time) initialize one object and have your dog go through at least 10 activities (you should have 10 different lines in which you call a method), print all the attributes every time you call a method - make sure you call all the methods you created - to check if the attributes are affected in the wanted way.
Validation criteria
- The linked file is available to anyone who has the link
- All the missions have been completed