Introduction à Python
=====================
Dans cette série, vous allez vous familiariser avec le langage Python.

Exercice 1 : Lire l'introduction à Python
-----------------------------------------
Lisez le `tutoriel de Python <https://docs.python.org/3/tutorial/index.html>`__. Si vous souhaitez travailler chez vous, téléchargez Python depuis `le site officiel <http://www.python.org/download/>`__. Pour les séances
d'exercices, vous aurez besoin de la version **3.x** de Python (ou ultérieure). Attention : les exercices ne sont pas compatibles avec Python 2.x.

Linux
~~~~~
Sous Linux, vous pouvez éditer vos fichiers sources avec votre éditeur préféré (vi, nano, ...). Cependant, nous vous recommandons d'utiliser gedit car il reconnaît la syntaxe de Python. Il existe plusieurs façons d'exécuter du code. La plus simple est la suivante :

::

    python3 monfichier.py

Python dispose d'une interface interactive permettant de débugger et de tester différentes commandes. Pour appeler l'interface, il faut lancer ``python3`` dans un terminal. Pour quitter l'interface, un simple ``exit()`` (ou ``Ctrl-D``) suffit.

Windows
~~~~~~~
Utilisez Linux... Sinon, `PyScripter <http://code.google.com/p/pyscripter/downloads/detail?name=PyScripter-v2.4.1.zip>`__ est un environnement open-source de développement Python. Une fois le fichier zip téléchargé, vous pouvez le décompresser dans le répertoire de votre choix, puis lancer l'exécutable.

Vous pouvez également utiliser un éditeur qui reconnaît la syntaxe de Python comme `Notepad++ <http://www.notepad-plus-plus.org/>`__ ou `PSPad <http://www.pspad.com/>`__. Vous pouvez ensuite exécuter votre code en ligne de commande en utilisant l'installation standard de Python :

::

    python3 monfichier.py

Le chemin vers l'exécutable ``python3`` doit être présent dans le paramètre système ``%PATH%``.

Exercice 2 : Bases du langage
-----------------------------
Quelques exercices tout `simples <http://fr.wikibooks.org/wiki/Programmation_Python_Exercices_Base_du_langage>`__.

Introduction rapide à la programmation objet en Python
------------------------------------------------------
Dans les séries à venir, nous utiliserons des types de structures de données abstraits (TDA). Python offre la possibilité de créer des classes et de manipuler des objets. La syntaxe complète pour la gestion des classes se trouve au Chapitre `9 du tutoriel de Python <https://docs.python.org/3/tutorial/classes.html>`__.

Afin de vous familiariser avec la syntaxe de Python, voici un petit exemple :

.. code-block:: python

    class Personne:
    
        def __init__(self, nom, age): 
            """ Constructeur. """
    
            self.nom = nom
            self.age = age
    
        def anniversaire(self):
            self.age += 1
    
    class Etudiant(Personne): # Héritage
    
        def __init__(self, nom, age, section):
            """ Constructeur. """
    
            Personne.__init__(self, nom, age) # Héritage
            self.section = section
    
        def __str__(self):
            """ Surcharge la fonction qui retourne une représentation de l'objet\
                sous forme de string.
            """
    
            return 'Etudiant {} a {} ans et est en section: {}'.format(self.nom, 
                                                                       self.age, 
                                                                       self.section)
    
        def change_section(self, section): 
            self.section = section
    
    
    def affiche_etudiants(etudiants):
        print('Listes des étudiants:')
        for etudiant in etudiants:
            print('\t' + str(etudiant))
    
    
    toto = Etudiant('Toto', 23, 'SSC')
    print(toto)
    toto.anniversaire()
    toto.change_section('INF')
    print(toto)

L'exemple ci-dessus affichera : 

::

    Etudiant Toto a 23 ans et est en section: SSC
    Etudiant Toto a 24 ans et est en section: INF

Étudions plus en détail cet exemple.

*  Tout d'abord, nous commençons par définir une classe ``Personne``. Ensuite, nous définissons un constructeur (``__init__ (self,...)``), qui met à jour les attributs ``nom`` et ``age``, et une méthode ``anniversaire``, qui incrémente d'une unité l'âge de la personne.
*  De plus, nous définissons une autre classe ``Etudiant``, qui est elle-même une sous-classe de ``Personne``. Comme vous pouvez le constater, le constructeur de la classe ``Etudiant`` fait appel au constructeur de la classe ``Personne`` pour initialiser les attributs ``nom`` et ``age`` (vu qu'ils sont hérités).
*  La méthode ``__str__(self)`` est une méthode de la classe ``object``. Elle est donc héritée, mais peut être surchargée. Dans la classe ``Etudiant``, la méthode ``__str__(self)`` retourne une string donnant une description de l'objet .

.. note::
    Contrairement à de nombreux langages de programmation, Python ne vous laisse pas choisir par quelle méthode sont passés les paramètres (par référence ou par valeur). Python travaille en *object-reference*, qui est en fait une combinaison du passage par référence et par valeur. Plus concrètement, si le paramètre est un objet mutable (une liste, un dictionnaire, notre classe Personne), alors l'objet est passé par référence. Si l'objet n'est pas mutable (nombre, string, tuple), alors le paramètre est passé par valeur.

.. note::
    Vu l'ambiguïté causée par le passage en paramètre, certaines fonctions (comme ``append``, ``extend``, ``sort``) retournent ``None`` lorsqu'on travaille sur des listes mutables (comme c'est le cas dans notre exemple). Ceci est normal, car il y a eu beaucoup de confusion dans le passé pour décider si ces fonctions devaient retourner un nouvel objet ou plutôt une référence sur l'ancien. La solution la plus simple est de **ne pas directement** retourner le résultat.

Pour mieux comprendre ce problème, considérez l'exemple ci-dessous : 

::

    toto = Etudiant('Toto', 23, 'INF')
    titi = Etudiant('Titi', 22, 'SSC')
    tata = Etudiant('Tata', 25, 'SSC')
    etudiants=[toto, titi, tata]
    print(etudiants.sort(key = lambda e : e.age))

qui affichera 

::

    None

tandis que 

::

    toto = Etudiant('Toto', 23, 'INF')
    titi = Etudiant('Titi', 22, 'SSC')
    tata = Etudiant('Tata', 25, 'SSC')
    etudiants=[toto, titi, tata]
    etudiants.sort(key = lambda e : e.age)
    affiche_etudiants(etudiants)

affichera 

::

    Liste des étudiants:
        Etudiant Titi a 22 ans et est en section: SSC
        Etudiant Toto a 24 ans et est en section: INF
        Etudiant Tata a 25 ans et est en section: SSC