Pratiques d'écriture de scripts Python

PythonPythonIntermediate
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans cette partie, nous examinons de plus près la pratique de la rédaction de scripts Python.

Ceci est un Guided Lab, qui fournit des instructions étape par étape pour vous aider à apprendre et à pratiquer. Suivez attentivement les instructions pour compléter chaque étape et acquérir une expérience pratique. Les données historiques montrent que c'est un laboratoire de niveau intermédiaire avec un taux de réussite de 56%. Il a reçu un taux d'avis positifs de 100% de la part des apprenants.

Qu'est-ce qu'un script?

Un script est un programme qui exécute une série d'instructions et s'arrête.

## program.py

instruction1
instruction2
instruction3
...

Jusqu'à présent, nous avons surtout écrit des scripts.

Un problème

Si vous écrivez un script utile, ses fonctionnalités et ses capacités vont grandir. Vous voudrez peut-être l'appliquer à d'autres problèmes connexes. Au fil du temps, il pourrait devenir une application critique. Et si vous n'y prêtez pas attention, il pourrait se transformer en un véritable bordel. Alors, organisons-nous.

Définir les choses

Les noms doivent toujours être définis avant d'être utilisés par la suite.

def carré(x):
    return x*x

a = 42
b = a + 2     ## Exige que `a` soit définie

z = carré(b) ## Exige que `carré` et `b` soient définies

L'ordre est important. Vous mettez presque toujours les définitions de variables et de fonctions vers le haut.

Définir des fonctions

Il est une bonne idée de regrouper tout le code lié à une seule tâche dans un seul endroit. Utilisez une fonction.

def lire_prix(nom_fichier):
    prix = {}
    with open(nom_fichier) as f:
        f_csv = csv.reader(f)
        for ligne in f_csv:
            prix[ligne[0]] = float(ligne[1])
    return prix

Une fonction simplifie également les opérations répétées.

anciens_prix = lire_prix('anciens_prix.csv')
nouveaux_prix = lire_prix('nouveaux_prix.csv')

Qu'est-ce qu'une fonction?

Une fonction est une séquence nommée d'instructions.

def nom_de_la_fonction(arguments):
  instruction
  instruction
 ...
  return résultat

N'importe quelle instruction Python peut être utilisée à l'intérieur.

def foo():
    import math
    print(math.sqrt(2))
    help(math)

Il n'y a pas d'instruction spéciale en Python (ce qui en facilite la mémorisation).

Définition de fonction

Les fonctions peuvent être définies dans n'importe quel ordre.

def foo(x):
    bar(x)

def bar(x):
    instructions

## OU
def bar(x):
    instructions

def foo(x):
    bar(x)

Les fonctions doivent seulement être définies avant d'être réellement utilisées (ou appelées) pendant l'exécution du programme.

foo(3)        ## foo doit déjà être définie

Du point de vue de la présentation, il est probablement plus courant de voir les fonctions définies de manière du bas vers le haut.

Style du bas vers le haut

Les fonctions sont considérées comme des briques de construction. Les blocs les plus petits/les plus simples sont placés en premier.

## myprogram.py
def foo(x):
  ...

def bar(x):
  ...
    foo(x)          ## Défini ci-dessus
  ...

def spam(x):
  ...
    bar(x)          ## Défini ci-dessus
  ...

spam(42)            ## Le code qui utilise les fonctions apparaît à la fin

Les fonctions ultérieures s'appuient sur les fonctions antérieures. Encore une fois, il s'agit seulement d'un point de style. Le seul élément important dans le programme ci-dessus est que l'appel à spam(42) soit placé en dernier.

Conception de fonctions

Idéalement, les fonctions devraient être une boîte noire. Elles ne devraient opérer que sur les entrées passées et éviter les variables globales et les effets de bord mystérieux. Vos principaux objectifs : Modularité et Prédictibilité.

Chaînes de documentation

Il est recommandé d'inclure une documentation sous forme d'une chaîne de documentation (doc-string). Les doc-strings sont des chaînes écrites immédiatement après le nom de la fonction. Elles alimentent help(), les IDE et d'autres outils.

def read_prices(filename):
    '''
    Lire les prix à partir d'un fichier CSV contenant des données nom,prix
    '''
    prices = {}
    with open(filename) as f:
        f_csv = csv.reader(f)
        for row in f_csv:
            prices[row[0]] = float(row[1])
    return prices

Une bonne pratique pour les doc-strings est d'écrire un court résumé d'une phrase de ce que fait la fonction. Si plus d'informations sont nécessaires, inclure un court exemple d'utilisation ainsi qu'une description plus détaillée des arguments.

Annotations de type

Vous pouvez également ajouter des indications de type optionnelles aux définitions de fonctions.

def read_prices(filename: str) -> dict:
    '''
    Lire les prix à partir d'un fichier CSV contenant des données nom,prix
    '''
    prices = {}
    with open(filename) as f:
        f_csv = csv.reader(f)
        for row in f_csv:
            prices[row[0]] = float(row[1])
    return prices

Les indications ne font rien sur le plan opérationnel. Elles sont purement informatives. Cependant, elles peuvent être utilisées par les IDE, les vérificateurs de code et d'autres outils pour faire plus.

Dans la section 2, vous avez écrit un programme appelé report.py qui affichait un rapport montrant les performances d'un portefeuille d'actions. Ce programme était composé de quelques fonctions. Par exemple :

## report.py
import csv

def read_portfolio(filename):
    '''
    Lire un fichier de portefeuille d'actions dans une liste de dictionnaires avec les clés
    name, shares et price.
    '''
    portfolio = []
    with open(filename) as f:
        rows = csv.reader(f)
        headers = next(rows)

        for row in rows:
            record = dict(zip(headers, row))
            stock = {
                'name' : record['name'],
               'shares' : int(record['shares']),
                'price' : float(record['price'])
            }
            portfolio.append(stock)
    return portfolio
...

Cependant, il y avait également des parties du programme qui ne faisaient que effectuer une série de calculs scriptés. Ce code apparaissait vers la fin du programme. Par exemple :

...

## Afficher le rapport

headers = ('Name', 'Shares', 'Price', 'Change')
print('%10s %10s %10s %10s'  % headers)
print(('-' * 10 +'') * len(headers))
for row in report:
    print('%10s %10d %10.2f %10.2f' % row)
...

Dans cet exercice, nous allons prendre ce programme et l'organiser un peu plus solidement autour de l'utilisation des fonctions.

Exercice 3.1 : Structurer un programme comme une collection de fonctions

Modifiez votre programme report.py de sorte que toutes les principales opérations, y compris les calculs et la sortie, soient effectuées par une collection de fonctions. Plus précisément :

  • Créez une fonction print_report(report) qui imprime le rapport.
  • Changez la dernière partie du programme de sorte qu'elle ne soit rien de plus qu'une série d'appels de fonction et aucun autre calcul.
✨ Vérifier la solution et pratiquer

Exercice 3.2 : Création d'une fonction de niveau supérieur pour l'exécution du programme

Prenez la dernière partie de votre programme et empaquetez-la dans une fonction unique portfolio_report(portfolio_filename, prices_filename). Faites en sorte que la fonction fonctionne de telle manière que l'appel de fonction suivant crée le rapport comme auparavant :

portfolio_report('/home/labex/project/portfolio.csv', '/home/labex/project/prices.csv')

Dans cette version finale, votre programme ne sera rien de plus qu'une série de définitions de fonctions suivies d'un seul appel de fonction à portfolio_report() à la toute fin (qui exécute toutes les étapes impliquées dans le programme).

En transformant votre programme en une seule fonction, il devient facile de l'exécuter avec différents entrées. Par exemple, essayez ces instructions de manière interactive après avoir exécuté votre programme :

>>> portfolio_report('/home/labex/project/portfolio2.csv', '/home/labex/project/prices.csv')
... regardez la sortie...
>>> files = ['/home/labex/project/portfolio.csv', '/home/labex/project/portfolio2.csv']
>>> for name in files:
        print(f'{name:-^43s}')
        portfolio_report(name, '/home/labex/project/prices.csv')
        print()

... regardez la sortie...
>>>
✨ Vérifier la solution et pratiquer

Commentaire

Python facilite grandement l'écriture de code de script relativement non structuré où vous avez simplement un fichier contenant une séquence d'instructions. Dans l'ensemble, il est presque toujours préférable d'utiliser des fonctions chaque fois que possible. A un moment donné, ce script va grandir et vous souhaiterez avoir un peu plus d'organisation. De plus, un fait peu connu est que Python exécute un peu plus rapidement si vous utilisez des fonctions.

Sommaire

Félicitations ! Vous avez terminé le laboratoire de script. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.