.. $Id: documentation.rst.in 14117 2011-05-11 08:12:37Z ycadour $ .. _python: http://www.python.org .. index:: structuration code ##################### Structuration du code ##################### .. index:: fonction ============= Les fonctions ============= - La définition d'une fonction se fait par le mot clé *def* suivi du nom de la fonction. - Les éventuels paramètres sont déclarés entre parenthèses. - Le caratère ':' délimite le début de la fonction. - Le bloc de la fonction est délimité par les indentations. Premier exemple:: >>> def say_hello(firstname, lastname): ... print ("Hello {} {}".format(firstname.title(), lastname.title())) ... >>> say_hello('Terry', 'gilliam') Hello Terry Gilliam Il n'y a pas de distinction entre les fonctions et les procédures en Python. Les procédures sont des fonctions qui ne retournent pas de résultat. Pour retourner un résultat on utilise la directive *return*. >>> def get_hello(firstname, lastname): ... return "Hello {} {}".format(firstname.title(), lastname.title()) ... >>> result = get_hello('terry', 'gilliam') >>> result 'Hello Terry Gilliam' >>> result2 = say_hello('terry', 'gilliam') Hello Terry Gilliam >>> result2 >>> ----------------------------- Les paramètres d'une fonction ----------------------------- Il existe 3 types de paramètre. .. index:: paramètres explicites Les paramètres explicites ######################### - Les paramètres explicites sont séparés par une virgule et peuvent être enrichis d'une valeur par défaut, ils sont dans ce cas optionnels. - Il est nécessaire de regrouper les paramètres optionnels à la fin de la liste des paramètres. - Les paramètres peuvent être nommés sans respecter un ordre précis. :: >>> def say_hello(firstname, gender='Mr', lastname=''): ... fullname = ' '.join([gender, firstname, lastname]) ... print("Hello {}".format(fullname)) ... >>> say_hello('Terry') Hello Mr Terry >>> say_hello('Yolande', 'Mme') Hello Mme Yolande >>> say_hello('Yolande', lastname='Moreau', gender='Mme') Hello Mme Yolande Moreau .. index:: paramètres non explicites Les paramètres non explicites ############################# - Les paramètres non explicites permettent de spécifier autant de valeurs que l'on souhaite sans qu'il soit nécessaire de les spécifier dans la signature de la fonction. - Ils sont fournis sous la forme *nom=valeur*, et sont accessibles à l'interieur de la fonction sous forme de dictionnaire. - Les paramètres non explicites sont préfixés d'une double étoile. :: >>> def show_actors(**actors): ... for actor, name in actors.items(): ... print("{}:{}" .format(actor, name)) ... >>> show_actors(actor1='Terry Gilliam', actor2='John Cleese') actor2:John Cleese actor1:Terry Gilliam .. index:: paramètres arbitraires Les paramètres arbitraires ########################## - Les paramètres arbitraires fonctionnent de la même manière que les paramètres non explicites mais ne sont pas nommés. - Il sont accessibles à l'intérieur de la fonction sous forme d'un tuple. - Les paramètres arbitraires sont préfixés d'une étoile. >>> def ajoute_acteurs(*actors): ... liste = [] ... for actor in actors: ... liste.append(actor) ... return liste ... >>> ajoute_cteurs('Terry Gilliam', 'John Cleese') ['John Cleese', 'Terry Gilliam'] Ces trois types de paramètres peuvent être utilisés dans une même fonction, dans ce cas leur ordre doit être le suivant: *def fonction(param1, param2=2, *arbitraires, **non-explicites):* .. index:: docstrings -------------- Les docstrings -------------- Les docstrings sont des chaines de caractères placées au début du corps des fonctions. Ils sont associés à la variable __doc__ de la fonction. >>> def get_full_name(firstname, lastname): ... """Retourne le nom complet""" ... return '{} {}'.format(firstname, lastname) ... >>> get_full_name.__doc__ 'Retourne le nom complet' >>> help(get_full_name) 'Retourne le nom complet' -------------- Les typages -------------- Avec Python 3.5, il est possible de déterminer le type des entrées/sorties de vos fonctions. Il suffit de respecter les règles décrites ici : https://docs.python.org/3/library/typing.html .. index:: classe =========== Les classes =========== Une classe est définie par le mot clé *class*. Exemple de classe >>> class Human: ... """Un humain""" ... firstname = '' ... lastname = '' L'instanciation d'une classe s'effectue en appelant la classe. :: >>> humain1 = Human() >>> humain2 = Human() Ces deux instances sont issues d'une même classe mais sont deux instances différentes. :: >>> id(humain1) 39754640 >>> id(humain2) 39754712 Accessibilité et modfication des attributs:: >>> humain1.firstname '' >>> humain1.firstname='John' >>> humain1.firstname 'John' .. index:: méthode ------------ Les méthodes ------------ - Les méthodes de la classe ont toutes comme premier paramètre l'objet instancié, par convention ce paramètre s'appelle *self*. - Le premier paramètre est fourni de manière transparente lors de l'appel de la méthode. :: >>> class Human: ... """Un classe représentant un humain""" ... firstname = '' ... lastname = '' ... def get_full_name(self): ... """Retourne le nom complet""" ... return '{} {}'.format(self.firstname, self.lastname) ... >>> human1 = Human() >>> human1.firstname = 'John' >>> human1.lastname = 'Cleese' >>> human1.get_full_name() 'John Cleese' .. index:: héritage ---------- L'héritage ---------- Python permet de définir l'héritage de classe de façon fort simple. :: >>> class Actor(Human): ... """Un acteur""" ... >>> actor1=Actor() >>> dir(actor1) ['__doc__', '__module__', 'firstname', 'get_full_name', 'lastname'] L'héritage multiple est supporté par python, mais en pratique il est fortement déconseillé. ------------ Constructeur ------------ Lors de l'instanciation d'une classe la méthode spéciale *__init__* est invoquée et prend en paramètre l'objet instancié par l'interpréteur. Cette méthode permet l'initialisation des attributs lors de l'instanciation d'une classe. :: >>> class Actor(Human): ... """Un acteur""" ... def __init__(self, firstname, lastname): ... self.firstname = firstname ... self.lastname = lastname ... >>> actor = Actor('John', 'Cleese') >>> actor.get_full_name() 'John Cleese' ------------------ Propriétés privées ------------------ Il est possible de définir des attributs privés en les préfixant d'un double '_'. L'attribut n'est alors pas accessible directement. :: >>> class Actor(Human): ... """Un acteur""" ... def __init__(self, firstname, lastname, gender): ... self.firstname = firstname ... self.lastname = lastname ... self.__gender = gender ... >>> actor1 = Actor('John', 'Cleese', 'Mr') >>> actor1.firstname 'John' >>> actor1.gender Traceback (most recent call last): File "", line 1, in AttributeError: Actor instance has no attribute 'gender' Mais cette protection n'est pas absolue, il est possible d'accéder à l'attribut de cette manière :: >>> dir(actor1) ['_Actor__gender', '__doc__', '__init__', '__module__', 'firstname', 'get_full_name', 'lastname'] >>> actor1._Actor__gender 'Mr' ====================== Créer un projet Python ====================== Cookie cutter est votre ami ! D'abord, il faut l'installer: https://cookiecutter.readthedocs.io/en/2.0.2/installation.html Puis, à partir d'un template: - pour une logique "github" (CI/CD) : https://cookiecutter-python.readthedocs.io/en/latest/tutorial.html - pour une logique "package local" : https://dev.to/chaps/creating-a-python-package-with-cookiecutter-3ik0 ========= Exercice ========= Création d’un jeu du pendu : 1 classe « JeuPendu », variables : nb_essais, mots, historique, méthode start() pour lancer l'application. Interaction via la console (fonction input("XXX")) Trame: script tests_pendu.py