From f5831c7d5d02b74f831204836e0115edcf11d1cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?xavier=20dupr=C3=A9?= Date: Sat, 31 Mar 2018 14:04:36 +0200 Subject: [PATCH] blog post, history, classes --- HISTORY.rst | 4 +- README.rst | 2 +- .../blog/2018/2018-03-31_classesfonctions.rst | 174 ++++++++++++++++++ _doc/sphinxdoc/source/c_classes/classes.rst | 8 + requirements.txt | 2 +- setup.py | 4 +- 6 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 _doc/sphinxdoc/source/blog/2018/2018-03-31_classesfonctions.rst diff --git a/HISTORY.rst b/HISTORY.rst index d000e920..48d51bf7 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -6,9 +6,9 @@ History current - 2018-03-31 - 0.00Mb ============================= -* `5`: fix .. only:: html in readme.rst (2018-03-29) +* `5`: fix .. only:: html in readme.rst (2018-03-29) 0.1.175 - 2017-10-05 - 0.02Mb ============================= -* `2`: finish the migration of latex (2017-06-10) +* `2`: finish the migration of latex (2017-06-10) diff --git a/README.rst b/README.rst index f31f286d..fe8b290e 100644 --- a/README.rst +++ b/README.rst @@ -31,7 +31,7 @@ README .. image:: https://badge.waffle.io/sdpython/teachpyx.png?label=ready&title=Ready :alt: Waffle - :target: https://waffle.io/teachpyx/teachpyx + :target: https://waffle.io/sdpython/teachpyx .. image:: http://img.shields.io/github/issues/sdpython/teachpyx.svg :alt: GitHub Issues diff --git a/_doc/sphinxdoc/source/blog/2018/2018-03-31_classesfonctions.rst b/_doc/sphinxdoc/source/blog/2018/2018-03-31_classesfonctions.rst new file mode 100644 index 00000000..29bdc2d4 --- /dev/null +++ b/_doc/sphinxdoc/source/blog/2018/2018-03-31_classesfonctions.rst @@ -0,0 +1,174 @@ + +.. blogpost:: + :title: C'est obligé les classes ? + :keywords: python, classes + :date: 2018-03-31 + :categories: classe + :label: blog-class-ou-fonction + + *Monsieur, c'est obligé d'utiliser les classes ?* + C'est une question qu'on me pose chaque année + lors des projets informatiques + et je réponds chaque année que non, les classes + ne sont pas obligatoires mais qu'elles ont le don + de simplifier l'écriture des programmes. + Le lanage :epkg:`Python` propose une des syntaxes + les plus explicites par rapport à d'autres langages + car il n'y a pas de paramètres cachés. + Le programme suivant calcule la somme et le produit + de deux entiers stockés dans un dictionnaire. + + .. runpython:: + :showcode: + + def deux_entiers_somme(de): + return de['i1'] + de['i2'] + + def deux_entiers_multiplication(de): + return de['i1'] * de['i2'] + + de = {'i1': 3, 'i2': 2} + s = deux_entiers_somme(de) + m = deux_entiers_multiplication(de) + print(s, m) + + Les deux fonctions ne sont applicables qu'à deux entiers. + Il paraît normal de les préfixer avec *deux_entiers* + pour signifier à celui qui les utiliser que ça ne sert + à rien de les utiliser pour autre chose. + Les classes permettent de regrouper formellement + ces deux fonctions. + + .. runpython:: + :showcode: + + class DeuxEntiers: + + def somme(de): + return de['i1'] + de['i2'] + + def multiplication(de): + return de['i1'] * de['i2'] + + de = {'i1': 3, 'i2': 2} + s = DeuxEntiers.somme(de) # _ --> . + m = DeuxEntiers.multiplication(de) # _ --> . + print(s, m) + + On a juste remplacé le signe ``_`` par ``.`` qui signifie + que la fonction cherchée est dans la classe qui précède ``.``. + Comme les deux entiers en questions sont toujours liés + aux fonctions qui les manipulent, il paraît normal de les + inclure dans la classe. + + .. runpython:: + :showcode: + + class DeuxEntiers: + + def __init__(self, de): # on accroche les données à la classe + self.de = de + + def somme(self): + return self.de['i1'] + self.de['i2'] + + def multiplication(self): + return self.de['i1'] * self.de['i2'] + + de = DeuxEntiers({'i1': 3, 'i2': 2}) + s = DeuxEntiers.somme(de) + m = DeuxEntiers.multiplication(de) + print(s, m) + + .. index:: méthode + + Comme le concept a beaucoup plu aux informaticiens, + ils ont cherché à simplifier l'appel aux fonctions qu'ils + ont appelé des *méthodes* : + + .. runpython:: + :showcode: + + class DeuxEntiers: + + def __init__(self, de): + self.de = de + + def somme(self): + return self.de['i1'] + self.de['i2'] + + def multiplication(self): + return self.de['i1'] * self.de['i2'] + + de = DeuxEntiers({'i1': 3, 'i2': 2}) + s = de.somme() # disparition de DeuxEntiers + m = de.multiplication() # disparition de DeuxEntiers + print(s, m) + + .. index:: attribut + + Ensuite, ils se sont penchés sur la simplification de la représentation + des deux entiers ``{'i1': 3, 'i2': 2}``. Et s'ils étaient considérés comme + des variables de la classe qui ont été renommés en *attributs*. + + .. runpython:: + :showcode: + + class DeuxEntiers: + + def __init__(self, i1, i2): + self.i1 = i1 # plus de dictionnaire + self.i2 = i2 + + def somme(self): + return self.i1 + self.i2 # plus de dictionnaire + + def multiplication(self): + return self.i1 * self.i2 # plus de dictionnaire + + de = DeuxEntiers(3, 2) # plus de dictionnaire + s = de.somme() + m = de.multiplication() + print(s, m) + + Les classes permettent de regrouper formellement + les fonctions qui ne s'appliquent toujours aux mêmes + données. Plus encore, ce nouveau concept a permis d'en + introduire un autre, l':ref:`par_classe_heritage`, qui + permet de réutiliser certaines fonctions, d'en remplacer + d'autres et d'en ajouter pour une autre situation. + + .. runpython:: + :showcode: + + class DeuxEntiers: + + def __init__(self, i1, i2): + self.i1 = i1 + self.i2 = i2 + + def somme(self): + return self.i1 + self.i2 + + def multiplication(self): + return self.i1 * self.i2 + + class DeuxEntiersModifies(DeuxEntiers): # héritage + + def multiplication(self): + return abs(self.i1 * self.i2) # modifié + + def division(self): + return abs(self.i1 / self.i2) # ajouté + + de = DeuxEntiersModifies(-3, 2) + s = de.somme() + m = de.multiplication() + d = de.division() + print(s, m, d) + + Cela peut paraît anodin mais la grande majorité des + programmeurs utilisent majoritairement les classes + une fois qu'ils les ont découvertes car elles + permettent d'organiser le code informatique + en bloc logique. diff --git a/_doc/sphinxdoc/source/c_classes/classes.rst b/_doc/sphinxdoc/source/c_classes/classes.rst index cbcc082f..2f5f06d7 100644 --- a/_doc/sphinxdoc/source/c_classes/classes.rst +++ b/_doc/sphinxdoc/source/c_classes/classes.rst @@ -361,6 +361,14 @@ Cette écriture devrait toutefois être évitée puisque la méthode li = [ nb.methode1(100) for i in range(0,10) ] print(li) # affiche [19, 46, 26, 88, 44, 56, 56, 26, 0, 8] +Ceux qui découvrent la programmation se posent toujours +la question de l'utilité de ce nouveau concept qui ne +permet pas de faire des choses différentes, tout au plus +de les faire mieux. La finalité des classes apparaît +avec le concept d':ref:`par_classe_heritage`. L'article illustre +une façon de passer progressivent des fonctions aux classes de +fonctions : :ref:`C'est obligé les classes ? `. + .. _par_classe_constructeur: Constructeur diff --git a/requirements.txt b/requirements.txt index 33112be8..28f747fe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ coverage jyquickhelper -pyquickhelper>=1.7.2468 +pyquickhelper>=1.7.2508 solar-theme wheel diff --git a/setup.py b/setup.py index 9b883b8c..74b59495 100644 --- a/setup.py +++ b/setup.py @@ -79,8 +79,8 @@ def is_local(): import_pyquickhelper() from pyquickhelper.pycode.setup_helper import available_commands_list return available_commands_list(sys.argv) - - + + def verbose(): print("---------------------------------") print("package_dir =", package_dir)