GERBELOTBARILLON.COM

Parce qu'il faut toujours un commencement...

Python

0. Introduction


Python est un langage multi paradigme, prenant en charge la programmation procédurale aussi bien que la programmation objet et dispose d'un nombre très important de bibliothèques. Cela lui permet d'être présent dans tous les domaines de l'informatique, des mathématiques, de la physique, de l'intelligence artificielle... Il est également présent sur les plates-formes les plus courantes du marché (Window, Mac, Linux) et ne cesse de s'améliorer.

Sa simplicité en fait un outil extrêmement puissant et efficace pour du test, de la validation de concepts que de la mise en exploitation. Son ouverture aux bibliothèques graphiques lui permet également de disposer d'un grand nombre d'interfaces graphiques.

Documentation officielle : https://www.python.org

1. Installation


Python pour Windows
Pour les autres systèmes, si c'est Linux ou équivament, Python 3 est normalement déjà installé. Sinon rendez-vous sur https://www.python.org pour télécharger la version qui correspond à votre environnement.

2. Table des matières

La console


Pour ceux qui l'auraient oublié, il existe une console par laquelle vous pouvez saisir des commandes et ce, sur l'ensemble des systèmes informatiques existants tels Windows, Mac, Linux, Amiga, C64 (pas sûr que python existe sur le C64 lol)... Sur Windows il suffit de faire Win + R et de taper cmd, sur Mac et Linux il faut chercher le terminal dans les menus. S'il n'y a pas d'interface graphique, alors c'est que vous êtes déjà en console. Dont acte. Il ne reste qu'à taper la commande

python
ou python3 pour certaines installations de Linux et Mac pour lancer l'interpréteur interactif de Python.

L'environnement REPL (Read-Eval-Print-Loop) est pratique pour valider des process ou des calculs, voire consulter les méthodes disponibles dans les packages que l'on souhaite utiliser dans nos programmes. Par exemple :

>>> print("Hello world")
Hello world
Simple ligne de texte sans fioriture.

>>> print("Hello\nWorld")
Hello
World
Même ligne mais en utilisant un caractère d'échappement \n pour imposer un retour à la ligne (newline en ASCII). Il en existe d'autres comme la tabulation (\t) qui permet de réaliser un décalage d'affichage de plusieurs espaces d'un coup.

>>> print("Hello" + " World")
Hello World
Utilisation de l'addition pour ajouter deux chaines de caractères (la concaténation)

>>> print("Hello \"Strange\" \t world")
Hello "Strange"          world
Utilisation de la fameuse tabulation qui produit un affichage décalé. Utilisation également de l'anti-slash (ou le backslash plus présent dans la littérature) pour déspécialiser un caractère.

>>> 10*2
20
Calcul simple de multiplication

>>> 10*2.5
25.0
Multiplication d'un entier par un nombre flottant qui donne un flottant comme résultat (fini avec un .0, appelé décimal)

>>> 43/3
14.333333333333334
Division de deux valeurs entières qui produit un résultat décimal

>>> 43//3
14
Division entière qui produit une valeur entière

>>> 43%3
1
Modulo de la division (le reste de la division entière)

>>> 6**2
36
Elévation d'un nombre à la puissance (ici élévation au carré)

Les éditeurs de code


Editer un code en langage python revient à utiliser un simple (ou pas) éditeur de texte que l'on trouve installé de base sur l'ensemble des systèmes d'exploitation comme nano, vim, notepad... Ce ne sont pas forcément les plus pratiques à utiliser, je vous l'accorde. C'est pour cela que la sélection ci-après reste intéressante à tester :

Les variables et les types


Il y a un nombre relativement restreint de types de données, sans fioriture.

VariableType PythonValeur utilisable
BooléenboolUne valeur booléenne est soit vraie soit fausse. Elle est évaluée True ou False en Python
EntierintUn nombre entier, comme 42 ou 44228542. Les entiers avec Python version 3 sont équivalents aux valeurs de type long. La valeur limite supportée est donnée par sys.maxsize à savoir 9223372036854775807, autrement dit 2**63 - 1 en environnement 64 bits. Sinon c'est 2**31 - 1 en environnement 32 bits. Mais 2**63 - 1 n'est pas la plus grande valeur manipulable par Python comme par exemple :
>>> i = 10**100
>>> print(i)
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Ce qui montre bien une valeur supérieure à sys.maxsize.
RéelfloatLes nombres réels permettent de contenir des valeurs infinies, comme l'est la déclaration de l'infini mathématique noté inf.
>>> print(float('inf'))
inf
Les valeurs min et max des flottants sont obtenues par la commande suivante
>>> print(sys.float_info)
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
ComplexecomplexUn nombre complexe exprimé sous la forme z = a + ib (z = 40 + 2i, z = 24 + 43i, ...). A la différence de l'écriture mathématique, Python permet la déclaration d'un nombre complexe par z = 4 + 5j (j au lieu de i). Les nombres complexes sont définis dans le packahe cmath qu'il faut donc importer avant usage.
Chainestring, strToute chaine de caractères, une phrase, un mot ou tout autre objet défini entre caractères " " ou ' '.
Il est possible de produire la conversion d'un type à l'autre en utilisant la fonction qui porte le nom du type que l'on souhaite affecter. Par exemple int() ou str() vont permettre de convertir une chaine en entier ou un entier en chaine de caractères. Si vous ne savez pas de quel type est votre variable, vous pouvez utiliser la fonction type() pour vous l'indiquer.

Les raccourcis pratiques du langage


Permuter deux éléments

Par défaut, dans la quasi majorité des autres langages, pour échanger le contenu de deux variables il faut utiliser temporairement une troisième variable pour faire a->c, b->a, c->b et ainsi échanger les éléments entre a et b.

Avec Python, c'est une opération plus simple car il suffit de faire a, b = b, a

>>> a = 10
>>> b = 5
>>> print(a, b)
10 5
>>> a, b = b, a
>>> print(a, b)
5 10

Affectations multiples

Imaginons que l'on souhaite affecter 4 valeurs à 4 variables distinctes. Il nous faudrait 4 instructions pour cela. Avec Python, il suffit de faire a, b, c, d = 1, 4, 42, 100

Les fonctions en Python


Un bloc de code pouvant être exécuté plusieurs fois de manière indépendante est appelé une fonction (programmation procédurale) ou méthode (programmation objet). La structure de déclaration est la même à savoir le mot clé def suivi du nom de la fonction et des arguments entre parenthèses.

def hello():
   print("Hello world")

Plus loin dans le code, pour appeler cette fonction il suffira juste de faire hello() une ou plusieurs fois selon les besoins et les activités de cette fonction.

Si la fonction dispose d'un argument, il peut être obligatoire ou optionnel (à savoir qu'il sera déclaré avec une valeur par défaut s'il n'existe pas lors de l'appel de la fonction).

def hello(name='Bob'):
print('Hello ' + name)
Les deux appels de fonction suivants sont valides et vont afficher des valeurs distinctes :
hello('Alice')  # va afficher 'Hello Alice'
hello()  # va afficher 'Hello Bob'

Les valeurs transmises en paramètre le sont par référence (pointeur mémoire) sauf pour les entiers, booléens, flottants, chaines et tuples. Ces types sont invariants et leur valeur ne changera pas en cas de modification dans une fonction.

def modifie(valeur):
   valeur = valeur + 2

val = 42
modifie(val)
print(val)  # Affiche 42 et non pas 44 comme on aurait pu s'y attendre.
Pour renvoyer une valeur modifiée, il faut utiliser le mot clé return suivi de la ou des valeurs à renvoyer au programme appelant. Cela peut être une valeur simple ou une série de valeurs séparées par des virgules, un tuple, un dictionnaire ou tout autre objet Python.

Les chaines de caractères


Python dispose d'un grand nombre de fonctions permettant de manipuler les chaines de caractères. Nous allons présenter ici une cheat sheet de ces dernières en mode simplifié. Contrairement aux listes, les fonctions sur les chaines travaillent toujours sur une copie de la chaine comme ch1 = "Bonjour".upper(). Dans cet exemple ch1 aura le contenu de la chaine modifié. La chaine source n'a pas changé.

FonctionDescriptionEntréeSortie
lower() Met toute la chaîne de caratères en minuscules BonJour bonjour
upper() Met toute la chaîne de caratères en majuscules Bonjour BONJOUR
capitalize() Met le début de la phrase avec une majuscule bonjour le monde Bonjour le monde
title() Met tous les mots avec une initiale en majuscule bonjour le monde Bonjour Le Monde
center(<largeur>, [caractère de remplissage]) Effectue un centrage par défaut de la chaine sur la largeur définie. Si un caractère de remplissage est défini, il sera utilisé pour remplacer les espaces normalement utilisés dans le centrage.
chaine = chaine.center(40, "-")
print(chaine)
------------Bonjour le monde------------
find(chaine, debut, fin)
index(chaine, debut, fin)
Recherche d'une sous chaine dans une chaine. La différence entre les deux est que find() va renvoyer -1 si la sous chaine n'est pas trouvée alors que index() va lever l'exception ValueError, qu'il faudra mettre dans un try/catch pour la traiter. print("bonjour le monde".find("le"))
print("bonjour le monde".index("le")

print("bonjour le monde".find("avion"))
print("bonjour le monde".index("avion")
8
8

-1
ValueError: substring not found
strip() Suuprime les caractère d'espace avant et après la chaine " Bonjour le monde " "Bonjour le monde"
replace(ancienne, nouvelle) Remplace une sous chaine par une autre "Bonjour le Monde".replace("o", "e") "Benjeur le Mende"
split() Découpe une chaine en une liste d'éléments "Bonjour le monde".split(" ") ["Bonjour", " le", "monde"]
isalpha(), isdigit(), isdecimal(), isnumeric(), isalphanum(), islower(), isupper(), isidentifier(), iskeyword() Série de fonctions qui vont permettre de tester si une chaine est en majuscules, minuscules, une suite de caractères alphanumeriques ou conmprend des mots réservés. "class".isidentifier() True

Les listes


La notion de listes est une notion extrêmement importante en Python. Elles sont très flexibles et peuvent contenir n'importe quel type d'objet sans distinction de type dans une même liste. Contrairement aux chaines de caractères, les traitements ne sont pas réalisés sur une copie mais bien sur les éléments de la liste elle-même.

Une liste est une séquence d'éléments qui est indicée et dont les éléments sont accessibles par un index.


inventaire = ["épée", "arc", "bouclier"]

# Parcourt la liste pour afficher tous ses éléments
for i in inventaire:
   print(i)

print(inventaire[0]) # affiche le premier objet de la liste

L'aspect intéressant d'une liste est de pouvoir n'afficher qu'une partie de la liste.


print(inventaire[:]) # affiche toute le liste
print(inventaire[-1]) # affiche le dernier élément
print(inventaire[1:]) # affiche la liste depuis le deuxième élément jusqu'à la fin
print(inventaire[::-1]) # affiche la liste depuis le dernier vers le premier élément
print(inventaire[1:2]) # affiche les éléments depuis le second et les deux suivants

L'ajout d'un élément dans une liste s'effectue simplement en faisant appel à la méthode append(item). Le nouvel élément sera positionné en fin de liste. Pour insérer un élément à une position donnée, il faut utiliser la méthode insert(position, item). Enfin pour supprimer un élément il est possible d'utiliser la méthode remove(item). Pour la suppression par rapport à un indice de la liste, il faut utiliser l'instruction del liste[indice].

Comme pour les chaines de caractères, il est possible d'utiliser les fonctions index() pour retrouver un élément dans une liste.

De même pour trier nous utilisons la fonction sort() et pour inverser une liste reverse(). La fonction clear() efface les éléments de la liste (tout comme liste = []) et la fonction len(list) renvoie le nombre d'éléments présents dans la liste. La fonction count(objet) retourne le nombre d'éléments du type objet dans la liste.

La fonction split() utilisée sur une chaine renvoie une liste de chaines. Pour faire l'inverse, à savoir prendre une liste de chaines et en faire une chaine il existe la fonction " ".join(liste).

inventaire = ["arc", "épée", "bouclier", "armure", "fléau"]
print(inventaire)

print(inventaire[1])

print(inventaire[::-1])

inventaire.sort()
print(inventaire)

print(len(inventaire))

inventaire.append("Masse d'arme")
print(inventaire)
inventaire.remove("bouclier")
print(inventaire)


chaine = "j'ai beaucoup d'armes dans mon inventaire"
armes = chaine.split()
print(armes)
armes = " ".join(armes)
print(armes)

Par défaut, lorsqu'une liste est référencée par une autre, il n'y a pas de copie. Toute modification sur l'une est reportée sur l'autre car nous travaillons sur les références des listes. Pour changer ce comportement il faut copier la liste source sur la liste cible par la fonction deepcopy() présente dans le module copy qu'il faut importer par import copy ou bien en faisant un liste_copie = liste_org[:].

Pour ajouter une liste à une autre il suffit d'utiliser liste2 = liste1.extend() ou bien liste2 += liste1.


liste1 = ['a', 'b', 'c']
liste2 = liste1
liste3 = liste1[:]
print("liste 1", liste1)
print("liste 2", liste2)
print("liste 3", liste3)
liste1[0] = 'z'
liste1.append(['d'])
print("liste 1", liste1)
print("liste 2", liste2)
print("liste 3", liste3)

Une liste étant un ensemble formé d'un index et d'une valeur, il est parfois utilie d'afficher l'index correspondant à la valeur.

for k, v in enumerate(nom_de_la_liste):
   print("Elément d'indice {} -> {}".format(k, v))
         

Les fonctions et méthodes à connaître pour être efficace avec les listes

Dans cette liste, les fonctions prennent une liste en paramètre tandis que les méthodes sont liées aux listes.


months = ['jan', 'fev', 'mar']
months.append('avr')
print(months) # ['jan', 'fev', 'mar', 'avr']

list = [1, 2, 3]
list.extend([4, 5, 6])
print(list) # [1, 2, 3, 4, 5, 6]

print(list.index('Fev')) # affiche 1

vals = [1, 2, 3, 4, 5, 42]
print(max(vals)) # 42

print(len(vals)) # 6

months.clear()
print(months) # []

list.insert(0, 42)
print(list) # [42, 1, 2, 3, 4, 5, 6]

fruits = ['fraises', 'framboises', 'fraises', 'fraises']
print(fruits.count('fraises')) # 3

f = fruits.pop(1)
print(f) # 'framboises'
print(fruits) # ['fraises', 'fraises', 'fraises']

fruits.remove('fraises')
print(fruits) # ['fraises', 'fraises']

liste = [1, 2, 3, 4, 5]
print(liste.reverse()) # [5, 4, 3, 2, 1]

aleatoire = [42, 4, 3, 77, 100]
print(aleatoire.sort()) # [3, 4, 42, 77, 100]

newlist = liste.copy()
print(newlist) # [1, 2, 3, 4, 5]
            

Les tuples


Les tuples sont des conteneurs de type séquence, similaires dans le principe des listes, mais qui ne peuvent pas être modifiés. Ils sont immuables et donc nous ne pouvont ni ajouter ni supprimer de valeurs. Ce sont généralement des objets utilisés pour manipuler des données constantes pour les retours de fonctions par exemple.


tuple = () # Création d'un tuple vide
tuple_simple = (42,) # Mettre une virgule pour forcer la création d'un tuple sinon cela sera considéré comme 
                     # le type de base utilisé (integer dans ce cas)
print(tuple[0]) # Affiche 42

Les dictionnaires


Un dictionnaire est une structure composé d'une clé et d'une valeur. Tous les types peuvent être utilisés dans un dictionnaire. Un dictionnaire est déclaré avec dico = {:}. Un dictionnaire n'est pas du tout ordonné.

dico_vide = {} # Dictionnaire vide
dico = {1:42, 2:63, 3:99} # dictionnaire avec clés de 1 à 3

print(dico[2]) # affiche la valeur 63 qui correspond à la clé 2.

dico_etudiant = {"prenom":"Jean", age:42}
print(dico[prenom]) # affiche Jean

Pour ajouter une valeur à un dictionnaire il suffit de faire dico[<cle>] = "valeur". Si cette clé existe déjà alors elle sera modifiée et sinon elle sera ajoutée. Pour supprimer un élément, il existe la méthode de dictionnaire nommée pop() en faisant v = dico.pop("élément") et renvoie la valeur supprimée. Autrement il faut utiliser del dico[<item>].

Il est possible de parcourir le dictionnaire soit sur ses valeurs soit sur ses clés en faisant:


for k in dico.keys():
   print(k)

for v in dico.values():
   print(v)

for k, v in dico.items():
   print("Clé : {} - Valeur : {}".format(k, v))

Les éléments pointant sur les dictionnaires sont des références à ces éléments. Pour obtenir une duplication d'une liste il faut utiliser la méthode de disctionnaire copy().


dico = {1:42, 2:63, 3:99} # dictionnaire avec clés de 1 à 3
dico2 = dico.copy()
print(dico)
print(dico2)
dico["chat"] = "miaou"
print(dico)
print(dico2)

Les paramètres nommés


Une fonction peut être appelée avec des paramètres simples


def fonction(p1, p2):
   print(f1, f2)

fonction(1, 2) # Affiche 1 2

Une fonction peut disposer de paramètres avec des valeurs par défaut qui seront utilisées si les paramètres ne sont pas passés lors de l'appel de la fonction

def fonction(p1=1, p2=41):
   print(p1, p2)

fonction(1, 2) # Affiche 1 2
fonction() # Affiche 1 41, valeur des paramètres par défaut
fonction(10) # Affiche 10 41

Il est possible de passer un nombre quelconque de paramètres nommés à une fonction. Celle-ci les utilisera comme un dictionnaire.


def fonction(**params):
   print(params)

fonction(p1="Jean", p2="Aymar", p3=42) # Affiche {'p1': 'Jean', 'p2': 'Aymar', 'p3': 42}

Les classes


Une méthode est simplement une fonction qui est déclarée dans un objet et utilisée par l'instance de l'objet.


class Humanoide:
   """
   Chaine utilisée pour donner des informations sur la classe. C'est le docstring.
   """

   planete = "Terre" # Attribut de classe disponible pour toutes les instances

   def __init__(self, nom, age):
      self.nom = nom
      self.age = age

   def parler(self, message):
      print("{} vous dit {}".format(self.nom, self.message))

   [ClassMethod]
   def voyager(cls, nouvelle_planete): # Méthode de classe
      Humanoide.planete = nouvelle_planete

   [StaticMethod]
   def Reve(): # Méthode statique
      print("Je voudrais voler avec les oiseaux.")

# Programme principal
   h1 = Humanoide("Freddy", 42)
   h1.parler("Faites de beaux rêves...")
   
   print("Je suis sur la planète {}".format(Humanoide.planete))
   Humanoide.voyager("Mars")
   print("Je suis arrivé sur la planète {}".format(Humanoide.planete))

   Humanoide.Reve() # appel d'une méthode de classe sans instanciation
         

Les Propriétés d'encapsulation


Une propriété a pour but essentiel d'effectuer des contrôles sur les valeurs que l'on affecte à des variables d'instance. Plutôt que de lire ou effectuer des modifications d'une variable, passer par une propriété permet de contrôler le comportement de cette variable.
Utiliser la fonction prop = property(getter, setter, deleter, helper) pour masquer un attribut de la classe et ne pas le rendre disponible pour accès ou modification depuis l'extérieur de la classe. Par ceonvention, les valeurs d'attributs ne devant pas être manipulées depuis l'extérieur de la classe sont préfixées par un caractère underscore '_'. Cela n'apporte aucun changement par rapport à un autre attribut mais est un élément visuel admis pour représenter ce type de variables.

Pour créer une propriété, il faut simplement mettre en place deux méthodes :

Les deux autres méthodes sont rarement utilisées et sont utilisées pour supprimer une variable et mettre un commentaire décrivant la propriété. Ainsi, la variable d'instance deviendra "invisible" depuis l'extérieur de cette instance et il ne sera plus possible de manipuler cette valeur autrement qu'en utilisant les méthodes prévues.


class Celsius:
   def __init__(self, temperature=0):
      self._temperature = temperature

   def to_farenheit(self):
      return str((self._temperature * 1.8) + 32) + " °F"

   def get_temperature(self):
      print("La température est de...")
      return str(self._temperature) + " °C"

   def set_temperature(self, value):
      print("Affectation de la température...")
      if value < -273.15:
         raise ValueError("Température impossible.")
      self._temperature = value

   # Création de la property qui fournit une interface à la variable privée _temperature
   temperature = property(get_temperature, set_temperature)


# Programme principal
humain = Celsius(37)
print(humain.temperature)
print(humain.to_farenheit())
humain.temperature = -500
         

L'affichage du résultat nous donne


La température est de...
37°C
98.60000000000001°F
Affectation de la température...
Traceback (most recent call last):
  File ".\properties.py", line 26, in 
    humain.temperature = -500
  File ".\properties.py", line 15, in set_temperature
    raise ValueError("Température impossible.")
ValueError: Température impossible.
Ce qui nous permet de voir que l'utilisation des propriétés apporte un niveau de contrôle et peut lever des exceptions

L'héritage


Lorsqu'une classe hérite d'une autre classe elle obtient de son parent tous les attributs et toutes les méthodes définies. Une classe fille est une spécialisation de la classe mère et va définir avec plus de précision les éléments de son parent. Le constructeur de la classe fille doit appeler le constructeur de la classe parente avec les paramètres du constructeur de la classe mère.


# Classe mère
class Vehicule:
   def __init__(self, nom, reservoir):
      self.nom = nom
      self.reservoir = reservoir

   def afficher(self):
      return self.nom + " avec réservoir de {} litres".format(self.reservoir)

   def deplacer(self):
      print("Le véhicule {} se déplace...".format(self.nom))

# classe fille qui hérite de la classe Vehicule
class Voiture(Vehicule):
   def __init__(self, nom, capacite, puissance):
      Vehicule.__init__(self, nom, capacite)
      self.puissance = puissance
      self.type = "Voiture"

   def afficherType(self):
      return self.type + " de {} chevaux".format(self.puissance)

   def deplacer(self):
      print("Je roule...")

# nouvelle classe fille qui hérite de la classe Vehicule
class Avion(Vehicule):
   def __init__(self, nom, capacite, puissance):
      Vehicule.__init__(self, nom, capacite)
      self.puissance = puissance
      self.type = "Avion"

   def afficherType(self):
      return self.type + " de {} chevaux".format(self.puissance)

   def deplacer(self):
      print("Je vole...")


# Programme principal
v = Voiture("Aston Martin Vantage", 90, 450)
print(v.afficher()) # Utilisation de la méthode de la classe mère
print(v.afficherType())
v.deplacer()

a = Avion("Rafale", 2500, 4000)
print(a.afficher())
a.deplacer()
         

Par défaut une classe fille va redéfinir les méthodes de la classe parente. Lorsqu'une méthode est appelée sur un objet, si elle n'existe pas, elle va être cherchée dans la classe mère. Si vous souhaitez déterminer si votre objet est une instance d'une classe, il faut utiliser la méthode isinstance(<classe_fille>, <classe_mère>) ou bien issubclass(<classe_mere>, <classe_fille>)

Les fichiers avec Python


Les fichiers peuvent être accédés en lecture (r), écriture (w), ajout en fin de fichier (a), lecture et écriture (x), binaire (b). Lorsqu'un fichier a été ouvert, il faut le refermer en fin de traitement par close(). Pour savoir si un fichier est fermé il suffit d'utiliser .closed().


fic = open("fichier", "r")
contenu = fic.read() # lecture du fichier en une seule fois
print(contenu)
fic.close()

fic = open("fichier", "r")
contenu = fic.readline() # lecture d'une seule ligne du fichier
print(contenu)
fic.close()

fic = open("fichier", "r")
contenu = fic.readlines() # Toutes les lignes du fichier sont transformées en une liste
print(contenu)
fic.close()

Fermer un fichier en fin de traitement est important pour éviter les éventuelles pertes d'information. Pour simplifier, Python dispose d'une structure d'appel with qui va générer un bloc d'instruction qui se chargera de libérer les ressources automatiquement.


# Pas besoin de fermer le fichier quand with est utilisé
with open("fichier", "r") as fic:
   print(fic.readlines())

# Ecriture dans un fichier
with open("fichier", "w") as fic:
   nombre = 42
   fic.write(str(nombre))
   fic.write("Je suis une chaine\n")
   fic.write("Et une autre encore...")

Pour pouvoir enregistrer des structures complètes de données comme des classes, il faut utiliser le module pickle. L'objet sera sauvegardé sous la forme d'un dump binaire. Pour sauvegarder nous utilisons pickle.Pickler(file_descriptor) et dump(). Pour lire des données d'un fichier nous ferons pickle.Unpickler(file_descriptor) et load().


import pickle

class Player:
   def __init__(self, nom, niveau):
      self.nom = nom
      self.niveau = niveau
   def whoami(self):
      print("{} ({})".format(self.nom, self.niveau))

joueur = Player("Freddy", 42)

# Sauvegarde de l'objet sous forme binaire
with open("player.data", "wb") as fic:
   record = pickle.Pickler(fic)
   record.dump(joueur)

# Lecture de ce qui a été sauvegardé en binaire
with open("player.data", "rb") as fic:
   record = pickle.Unpickler(fic)
   joueur = record.load()

joueur.whoami() # doit afficher les informations sauevagrdées

Les packages


Ouvrir une commande MS-DOS et lancer la commande pip install extension_name.

Par exemple, pour installer numpy, une extension de gestion des calculs numériques, il suffira de faire pip install numpy. Si une erreur du type Unable to find vcvarsall.bat survient, c'est que le script pip n'arrive pas à trouver un compilateur C installé sur votre machine pour réaliser la mise en place de numpy.

Pour résoudre ce problème, il faut réaliser une des opérations suivantes :

Si vous disposez déjà d'une version de Visual Studio, modifiez le fichier de script python comme suit : Editez le fichier c:\Python34\Lib\distutils\msvc9compiler.py et remplacez productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, "productdir") par productdir = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC". Le chemin d'accès peut être différent selon la version de Visual Studio dont vous disposez.

Python dispose d'un certain nombre de fonctions et modules d'origine. Mais ce qui fait sa force est sa modularité. Pour utiliser des packages externes, que certains nomment bibliothèques ou includes, il est nécessaire de les installer et de les importer. Pour les installer, depuis une ligne de commande il faut saisir :

pip install nom_du_module
Pour les utiliser, il faut les importer dans le code, généralement en début de programme.
import os, sys
print("Le nombre de la vie est 42")
os.system("pause")
sys.exit()
Le morceau de code précédent importe deux modules déjà existants dans python qui traitent des actions de l'Operating System (package os) et de celles du système (package sys). Pour Linux, système sur lequel la commande système PAUSE n'existe pas, il faut saisir
input("Appuyez sur une touche")
pour créer la temporisation de l'action utilisateur.

Information importante : la fonction input() renvoie toujours une valeur de type chaine de caractères. A vous de bien valider son type et de l'affecter correctement pour ne pas perdre d'information lors de la conversion.

Les images


Une image est une suite de valeurs numériques décrivant les niveaux de couleur rencontrés sur chaque pixel composant l'image. La couleur peut être définie sur le principe du RGB (Red, Green, Blue) avec des valeurs de 0 à 255 sur chaque couleur. Mais peut également être gérée par les principes de Hue (Teinte), Saturation et Luminosité (HSL - Hue, Saturation, Lightness), avec des valeurs également entre 0 et 255. La façon de représenter les couleurs est plus compliquée car il y a une proportion entre les couleurs. Ainsi un rouge pur serait exprimé comme T = 0 - S = 240 - L = 120.

Cependant le plus simple reste d'utiliser la notation HTML qui est exprimée par un nombre hexadécimal du type #RRGGBB. Ainsi le rouge pur compliqué en HSL devient #FF0000 en hexadécimal. Ce qui est vraiment bien plus lisible non ???

En Python il existe une bibliothèque (un package) très pratique pour la gestion des images : Pillow. Pour le mettre en route, il faut l'installer par pip install pillow et l'importer par from PIL import ImageTk, Image. On peut ensuite affecter cette image en l'ouvrant par

img = Image.open("image_name.ext")
img.show()
De nombreuses informations peuvent être récupérées en exploitant les méthodes de l'objet Image : width, height, getpixel((x,y)) ou bien size() qui renvoie en une seule instruction les valeurs de largeur et de hauter de l'image.
from PIL import Image
img = Image.open("image.png") # ou JPEG ou autre
print(img.width)
print(img.height)
print(img.getpixel((100,100)))
img.show()

Le pendant de la fonction getpixel() est la fonction putpixel(dest, rgb) qui va mettre en destination (x, y) la valeur de couleur représentée par le triplet (r, g, b), chaque élément r, g,b pouvant prendre des valeurs entre 0 et 255. L'image ainsi modifiée (ou non) peut être sauvegardée par un appel à la méthode save("nom du fichier").

Une autre information intéressante est de pouvoir disposer des différents plans d'affichage RGB + canal Alpha (transparence) que l'on obtient avec la méthode split() qui renvoie un tuple avec les éléments (R, G, B, A).

>>> (r,g,b,a) = img.split()
>>> r.show()

Et comme l'un ne va pas sans l'autre, à split() correspond la méthode merge() qui va permettre de reprendre les différents plans de l'image afin de la recomposer.

>>> z = Image.merge("RGB", (r, g, b))
>>> z.show()

On peut également créer de toutes pièces une image par la méthode new() comme

newpic = Image.new("RGB", (800, 600), (255, 0, 0))
qui va créer une image de 800 x 600 pixels totalement rouge.

Et sur une image (zone mémoire particulière) on peut coller une autre image par la méthode paste().

destimg.paste(newpic, (0, 0))