Archives Wild Code School
Python

Object Oriented Programming - Intro to Classes

Quête 48 sur 66 · 1 image archivée

Intro

Imagine que tu travailles pour une entreprise de médias. Ton travail tourne autour du scraping (récupération automatique d'informations sur le Web) de certaines informations. Tu as plusieurs fonctions que tu utilises tous les jours (par exemple une fonction qui attrape des données précises sur une page et les met dans une base de données) et tu t'appuies toujours sur la même information (par exemple, combien de lignes tu as remplies). Comme tu as besoin au quotidien à la fois de fonctions et de variables qui tournent autour d'un sujet précis, tu décides de toutes les regrouper. Tu décides de créer une classe.

'[...] une classe est une façon de regrouper des fonctions (en tant que méthodes) et des données (en tant que propriétés) dans une unité logique qui tourne autour d'un certain type de chose. Si tu n'as pas besoin de ce regroupement, pas besoin de créer une classe. [...]' - d'après cette source.

Contenu

Pendant cette semaine, tu vas apprendre :

✅ ce qu'est une classe (cette quête), ✅ tous les éléments qui composent une classe (la quête suivante), ✅ comment utiliser une classe (la quête d'après), ✅ les 4 principes de la programmation orientée objet (Object Oriented Programming) (la quête d'après).

Qu'est-ce qu'une classe ?

Tu te souviens du Tamagotchi ? Tu en as déjà eu un ?

Tamagotchi Image

Tu penses peut-être que ce n'est qu'un vieux jeu, mais les Tamagotchis sont en réalité un très bon exemple de classes.

Pense à la façon dont ça marchait à l'époque. D'un côté, tu pouvais vérifier comment allait ton chat (ou ton chien), en consultant toutes les valeurs liées au chat (ou au chien) lui-même : niveau de fatigue, niveau de faim, saleté, et ainsi de suite. Tu pouvais consulter ces valeurs, mais tu n'avais pas le droit de les modifier directement. Par exemple, si ton chat était fatigué, tu ne pouvais pas changer le niveau de fatigue directement, tu pouvais seulement le border pour qu'il dorme. Tu devais utiliser une fonction pour modifier une variable parce que l'accès direct à la variable n'était pas autorisé. En le bordant pour qu'il dorme, le niveau de fatigue baissait et ton chat était moins fatigué.

C'est ce qui se passe dans une classe. Il y a des valeurs (appelées attributs, attributes) et des fonctions (appelées méthodes, methods) qui décrivent toutes l'état d'une certaine chose et toutes les actions que tu peux effectuer sur cette chose. Avec les classes, tu pourrais en fait modifier directement la valeur de l'attribut dans certains cas, mais utiliser les méthodes pour modifier la valeur contenue dans les attributs est considéré comme une façon plus sûre de programmer.

D'ici la fin de cette quête, on aura écrit une partie du code du chat Tamagotchi et d'ici la fin des 4 quêtes, on sera capables d'écrire tout le jeu et d'y apporter des modifications. Par exemple, on écrira la fonction pour qu'il joue mais pas celle pour qu'il prenne un bain (tu es la bienvenue pour l'ajouter et introduire de nouvelles choses pour personnaliser le jeu). La structure serait la même, donc tu es libre de rendre le jeu aussi détaillé et réaliste que tu veux en ajoutant des attributs (variables décrivant l'état de la classe) et des méthodes (actions pour modifier l'état de la classe).

Si tu veux, tu peux suivre cette quête et les suivantes en gardant ouverte la page de documentation des classes Python comme référence.

Comment reconnaît-on les classes ?

Comment savoir si on utilise une classe ? Il existe plusieurs façons de le repérer, en voici quelques-unes :

  • Si tu utilises la structure variable.function(), ta variable est un objet d'une classe (et cette fonction précise s'appelle une méthode)
  • si tu vérifies le type et que c'est <class ...>, c'est une classe
  • Si quelque chose commence par une majuscule, il y a de fortes chances que ce soit une classe (ou alors tu ne suis pas les conventions d'écriture de code ^^' )

Classe VS Objet

Puisque c'est une quête de programmation orientée objet, où sont les objets ?

Les objets sont les variables que tu crées à partir de la classe. Le type de chaque objet est une classe. Dans notre exemple Tamagotchi, le chat générique du jeu est la classe. Ensuite tu lances le jeu, tu crées ton chat. Peut-être que tu l'appelles Fluffy, Moon, Pow, Captain Meow, ... Ce sont tous des chats, ils viennent de la même classe. On les appelle des instances de la classe « Cat ».

Quand on définit une classe, on écrira :

python
class Cat:
  # rest of the code

Les classes sont généralement capitalisées pour signaler que ce sont des classes. Si on veut créer un objet à partir de cette classe, on écrira :

python
captain_meow = Cat(...)  # Additional parameters could be added inside the parenthesis

Cette dernière ligne te rappelle-t-elle du code que tu as déjà utilisé ?

hidden
Click to reveal|||text||||||0|||Hide

Yes, the creation of an empty dataframe:

`df = pd.DataFrame()`


DataFrame has been a class all along. You'll see that you have been using classes since you have started coding.

Définir une classe. Les constructeurs et « self »

Première chose, on doit définir la classe. La classe est la chose générale qui nous intéresse. Pour donner un nom qui a du sens à ta nouvelle classe, il est conseillé d'utiliser le nom de ton sujet d'intérêt. Pour revenir à notre exemple, Captain Meow ne nous intéresse pas encore vraiment. Pour l'instant, c'est juste « le chat » qui nous intéresse. Dans le cas du Tamagotchi, c'est le chat ou le chien, on continuera avec le chat.

Pour définir une classe, tu peux utiliser cette structure :

class class_name:
  def __init__(self, additional input variable):
    # rest of your code

La fonction à la deuxième ligne du code est une méthode, une fonction définie à l'intérieur d'une classe et utilisée uniquement pour traiter les objets de cette classe précise. Cette méthode bien particulière, __init__, s'appelle un constructeur (constructor) : une méthode utilisée pour initialiser l'état d'un objet.

Dans notre exemple du chat, elle aura le code suivant :

python
class Cat: 
  def __init__(self, name):  # name is an additional parameter
    # We will see next what to write in here
À propos du constructeur

Tu as peut-être remarqué que cette méthode a des underscores (tirets bas) dans son nom. C'est une convention de programmation pour signaler les méthodes destinées à être invoquées indirectement. Le préfixe underscore est pensé comme un indice pour un autre programmeur : une variable ou une méthode commençant par un seul underscore est destinée à un usage interne. Cette convention est définie dans la PEP 8 (« Python Enhancement Proposals », ce sont les guides de style du langage de programmation). Ce n'est pas imposé par Python, mais c'est bien de la suivre quand même : ça rendra ton code plus facile à lire pour les autres codeurs et pour ton-toi-futur. Pour la même raison, les noms des classes sont écrits avec une majuscule.

↗
↗

Dans ce cas, tu ne verras jamais cette méthode appelée. Le constructeur intervient implicitement quand tu crées un objet, pour l'initialiser. Ici, d'après notre exemple, on devrait initialiser notre objet-chat avec un nom, comme ça :

python
captain_meow = Cat('Captain Meow') 

Dans ce cas, l'interpréteur comprend que « Captain Meow » est la variable name de l'objet chat. La méthode __init__ n'a jamais été tapée dans le code (donc elle est implicite) mais elle a quand même été appelée.

Pendant qu'on continuera à développer notre classe, tu verras qu'il y a des méthodes implicites, mais aussi des méthodes explicites, celles qui seront explicitement appelées.

À propos de « self »

Le nom self est typique des classes. Tu ne l'as peut-être jamais remarqué parce qu'il est écrit dans le code mais il a été retiré de la documentation en ligne. Il est utilisé comme premier paramètre d'entrée d'une méthode. Ça veut dire qu'en gros il passe son-objet-lui-même à la fonction. Tu as déjà vu self à l'œuvre tellement de fois.

Voici un exemple :

python
import pandas as pd

# Some data
some_data = {'col1': [2, 4, 6, 8, 2], 'col2' : [3, 5, 4, 2, 6]}

# Build the dataframe using the class init
specific_dataframe = pd.DataFrame(some_data)

# Call the method
specific_dataframe.info()

Dans ce cas, la variable specific_dataframe est un DataFrame, et DataFrame est une classe en Python. specific_dataframe est l'objet. Vérifions, exécute la ligne suivante :

python
print(type(specific_dataframe))

Maintenant, le titre de la méthode (fonction de la classe pandas.core.frame.DataFrame) n'a aucun paramètre d'entrée, alors comment sait-elle quelle est la variable à traiter ? La réponse est : « Parce qu'elle y est attachée ! specific_dataframe est la variable ». Exactement ! specific_dataframe est la variable, l'instance de la classe.

Dans le code source, la méthode est écrite :

class DataFrame:
  ...
  def info(self, ... ):
    # rest of the code

Dans ce cas, self recevra la variable specific_dataframe. La variable est passée implicitement dans la méthode et traitée. La valeur de sortie est renvoyée, mais elle peut aussi être stockée.

Peux-tu donner un exemple de méthode qui stocke la valeur de sortie dans l'objet qu'elle est en train de traiter ?

hidden
Click to reveal|||text||||||0|||Hide|||
`df.drop(... , inplace = True)`

In this case, the `df` is the object, the `pd.DataFrame` is the class, and the `drop` is the method.
↗

Regarde ici pour la documentation en ligne, celle qui n'a pas de « self » à lire

↗

Regarde ici pour le code source avec le « self » - celui de la ligne # 565.

quiz
false|||false|||true
# Comment reconnais-tu une classe ?
[] Le nom est écrit avec une majuscule
[] Si tu affiches le type, il imprime 'class...'
[] Il y a la possibilité d'écrire quelque chose comme variable.function()
[x] Toutes les réponses ci-dessus
# Qu'est-ce qu'un constructeur ?
[] C'est un attribut interne qui sert à stocker la valeur la plus importante de la classe
[x] C'est une méthode interne qui est appelée automatiquement quand l'objet est créé
[] C'est un nouveau langage de programmation, appelé ainsi pour souligner l'importance de l'architecture du code
# Les classes sont les variables spécifiques et les objets sont les types des classes.
[] Vrai
[x] Faux
# Qu'est-ce que self ?
[] C'est le nom d'un attribut
[] C'est une classe
[x] C'est le nom d'une variable interne utilisée dans les classes

Intro

Imagine you are working for a media company. Your work revolves around scraping certain information fro the Web. You have several functions that you use daily (for example a function that grabs specific data off a page and puts it into a database) and always rely on the same piece of information (for example, how many rows you filled). Since you need both functions and variables revolving around a specific topic daily, you decide to group all of those together. You decide to make a class.

'[...] a class is a way of grouping functions (as methods) and data (as properties) into a logical unit revolving around a certain kind of thing. If you don't need that grouping, there's no need to make a class. [...]' - from this source.

Content

During this week, you are going to learn:

✅ what is a class (this quest), ✅ all the elements that make up a class (next quest), ✅ how to use a class (quest after that), ✅ 4 Principles of Object Oriented Programming (quest after that).

What is a class?

Do you remember Tamagotchi? Have you ever had one?

Tamagotchi Image

Some of you might think it's just an old game, but Tamagotchis are actually a great example of classes.

Think about how it worked back in the day. On one side, you could check how your cat (or dog) was doing, by checking all the values related to the cat (or dog) itself: level of sleepiness, level of hunger, dirtiness, and so on. You could check these values, but you weren't allowed to change those values directly. For example, if your cat was tired, you couldn't change the level of sleepiness directly, you could only tuck him to sleep. You had to use a function to change a variable because direct access to the variable wasn't allowed. By tucking them to sleep, the sleepiness level went down and your cat was less tired.

This is what happens in a class. There are values (called attributes) and functions (called methods) all describing the state of a certain thing and all the actions you can take in respect to the certain thing. With classes, you could actually change the attribute's value directly in some cases, but using the methods to change the value in the attributes is considered a safer way to program.

By the end of this quest, we'll have written some of the code for the Tamagotchi cat and by the end of the 4 quests, we will be able to write the whole game and make changes. For example, we'll write the function for it to play but not the one for it to bathe (you are welcome to add that and introduce new things to personalize the game). The structure would be the same, so you are welcome to make the game as detailed and realistic as you want by adding attributes (variables describing the state of the class) and methods (actions to alter the state of the class).

If you want, you can go through this quest and the following ones while keeping open the Python class documentation web page for reference.

How do we recognize classes?

How do we know if we are using a class? There are several methods, here are some of them:

  • If you are using the structure variable.function(), your variable is an object of a class (and that specific function is called a method)
  • if you check the type and it's <class ...>, it's a class
  • If something starts with a capital letter chances are it's a class (or you are not following the code writing guidelines ^^' )

Class VS Object

Since this is a Object Oriented Programming Quest, where are the Objects?

The Objects are the variables you create from the class. The type of each object is a class. In our Tamagochi example, the generic cat in the game is the class. Then you start the game, you create your cat. Maybe you call it Fluffy, Moon, Pow, Captain Meow, ... These are all cats, they come from the same class. We call these instances of the class "Cat".

When we define a class, we will write:

python
class Cat:
  # rest of the code

Classes generally are capitalized to signal they are classes. If we want to create an object from that class, we will write:

python
captain_meow = Cat(...)  # Additional parameters could be added inside the parenthesis

Does this last line remind you of any code you have already used?

hidden
Click to reveal|||text||||||0|||Hide

Yes, the creation of an empty dataframe:

`df = pd.DataFrame()`


DataFrame has been a class all along. You'll see that you have been using classes since you have started coding.

Define a class. Constructors and "self"

First thing, we need to define the class. The class is the general thing we are interested in. To have a meaningful name for your new class it is suggested that you use the name of your topic of interest. Going back to our example, we are not really interested in Captain Meow yet. At the moment we are just interested in "the cat". In the Tamagotchi case, it's the cat or the dog, we'll move forward with the cat.

To define a class you might want to use this structure:

class class_name:
  def __init__(self, additional input variable):
    # rest of your code

The function in the second line of the code is a method, a function defined inside a class and used only to process objects from that particular class. This very specific method, __init__, is called a constructor: a methods that is used to initialize an object's state.

In our cat example, it will have the following code:

python
class Cat: 
  def __init__(self, name):  # name is an additional parameter
    # We will see next what to write in here
About the Constructor

You might have noticed that this method has underscores in its name. This is a programming convention to signal methods that are intended to be invoked indirectly. The underscore prefix is meant as a hint to another programmer that a variable or method starting with a single underscore is intended for internal use. This convention is defined in PEP 8 ("Python Enhancement Proposals", they are the Programming Language Style Guide). This isn't enforced by Python, but it's good to follow it nonetheless: it will make your code more easily readable by other coders and your-future-self. For the same reason, classes' names are written capitalized.

↗
↗

In this case, you'll never see this method called. The constructor implicitly intervenes when you create an object, to initialize it. In this case, according to our example, we should initialize our cat-object with a name, like this:

python
captain_meow = Cat('Captain Meow') 

In this case, the interpreter understands that "Captain Meow" is the cat's object name variable. The __init__ method was never typed in the code (therefore it's implicit) but it was called nonetheless.

While we'll continue developing our class, you'll see there are implicit methods, but also explicit methods, the ones that will be explicitly called.

About "self"

The name self is typical of classes. You might have never noticed it because it's written in the code but it's been removed from the online documentation. It is used as the first input parameter of a method. It means that basically passes its-object-self to the function. You have already seen self in action so many times.

Here is an example:

python
import pandas as pd

# Some data
some_data = {'col1': [2, 4, 6, 8, 2], 'col2' : [3, 5, 4, 2, 6]}

# Build the dataframe using the class init
specific_dataframe = pd.DataFrame(some_data)

# Call the method
specific_dataframe.info()

In this case, the variable specific_dataframe is a DataFrame, and DataFrame is a class in Python. specific_dataframe is the object. Let's check, run the following line:

python
print(type(specific_dataframe))

Now, the method title (function of the class pandas.core.frame.DataFrame), doesn't have any input parameters, so how does it know which is the variable to process? The answer is: "Because it's attached to it! specific_dataframe is the variable". Exactly! specific_dataframe is the variable, the instance of the class.

In the source code, the method is written:

class DataFrame:
  ...
  def info(self, ... ):
    # rest of the code

In this case, self will receive the variable specific_dataframe. The variable gets passed implicitly in the method and processed. The output value is returned, but it can also be stored.

Can you tell an example of a method that stores the output value back in the object it's processing?

hidden
Click to reveal|||text||||||0|||Hide|||
`df.drop(... , inplace = True)`

In this case, the `df` is the object, the `pd.DataFrame` is the class, and the `drop` is the method.
↗

Check here for the online documentation that has no "self" to be read

↗

Check here for the source code with the "self" - one in # line 565.

quiz
false|||false|||true
# How do you recognize a class? 
[] The name is written capitalized
[] If you display the type, it prints 'class...'
[] There is the possibility to write something like variable.function()
[x] All of the above
# What's a constructor?
[] It's an internal attribute to store the most important value of the class
[x] It's an internal method that is called automatically when the object is created
[] It's a new programming language, called this way to emphasize the importance of the architecture of the code
# Classes are the specific variables and Objects are the types of the Classes.
[] True
[x] False
# What is self?
[] It's the name of an attribute
[] It's a Class
[x] It's the name of an internal variable used in Classes