Apprendre Python

Un tuto pour découvrir Python tout en douceur

a marqué ce sujet comme résolu.

Tout le monde se secoue ! :D

J’ai commencé (vendredi 25 novembre 2022 à 15h38) la rédaction d’un tutoriel au doux nom de « Apprendre Python » et j’ai pour objectif de proposer en validation un texte aux petits oignons. Je fais donc appel à votre bonté sans limites pour dénicher le moindre pépin, que ce soit à propos du fond ou de la forme. Le tutoriel n’est pas encore totalement achevé mais les deux premières parties le sont, ainsi que les deux premiers chapitres de la troisième.

Vous pourrez consulter la bêta à votre guise à l’adresse suivante :

Merci !

+1 -0

Hello hello,

J’ai lu que le début et je constate que tu as prévu de démarrer de zéro, quitte à commencer par parler d’algorithmie.

Mon avis perso c’est que c’est pas une bonne idée car tu vas trop vite sur l’algo et tu perds ton lecteur là. Je sais que c’est parce que tu vas revenir et qu’en fait tout ton cours est plus ou moins à propos d’algo au final, mais le lecteur ne le sait pas à ce stade.

C’est un peu comme - et là c’est plutôt objectif - quand tu commences un paragraphe à propos de l’invite de commande python alors que ça sort de nul part et que le lecteur n’a aucune idée de comment l’installer/le lancer en réalité.

En tous les cas je te souhaîte bien du courage pour l’écriture de ton cours car c’est réellement long et fastidieux pour faire quelque chose de compréhensible par quelqu’un d’autre que nous même ;) .

Dans un premier temps, je me permets de saluer les efforts qui ont été fournis pour l’écriture de ce tutoriel.

Dans un second temps, je me permets de faire remarquer qu’il existe déjà un tutoriel à ce sujet sur le site.

Loin de moi l’idée de rejeter ce que tu as écris, je me demande simplement s’il est concevable de publier un contenu déjà existant.

Salut,

Il pourrait effectivement être préférable d’écrire un tutoriel sur une partie que tu connais bien et qui t’intéresse plutôt que de te lancer dans un tuto global. Ce n’est pas qu’avoir deux tutos généraux sur Python soit fondamentalement un problème, c’est surtout que pour que ce soit intéressant (pour les lecteurs, mais aussi pour le rédacteur qui investit du temps dans l’écriture du contenu !), il faut qu’il apporte quelque chose que le premier n’a pas. Par exemple une approche ou une pédagogie différente.

Par ailleurs, et plus embêtant, il y a tout de même de nombreuses approximations/erreurs dans ce qui a été rédigé jusqu’à présent. J’ai l’impression que tu manques un peu de recul sur le fonctionnement de Python et sur la programmation en général. Si ce n’est pas forcément bloquant pour rédiger un tutoriel sur le sujet, ça veut tout de même dire que l’effort de rédaction pour être à la fois clair et exact sera d’autant plus important que tu vas viser large avec le tuto.

Je mets trois exemples de trucs qui m’ont interpellés à la lecture.


Ce que l’on appelle, dans le jargon de l’informatique, une variable, c’est une chambre à laquelle on a donné un nom. Elles portent leur nom du fait que l’occupant de la chambre peut varier.

En réalité, ces "chambres d’hôtel" sont des emplacements de mémoire sur votre mémoire vive (RAM), et les "numéros de chambre" des adresses mémoire en binaire.

La métaphore des chambres d’hôtels avec des noms sur la porte et le contenu qui change pour représenter des emplacements mémoire avec des noms de variable la valeur associée est pas trop mauvaise pour certains langages, mais se casse la gueule en Python. En Python, une variable est plutôt une étiquette faiblement associée à une valeur, et complètement séparée de l’emplacement mémoire d’une part (c’est un truc que Python abstrait), et des changement potentiels de cette valeur (on peut changer la valeur des objets mutables sans déplacer l’étiquette, et on peut aussi déplacer l’étiquette sur un autre objet). Pour reprendre ton analogie, les variables seraient plutôt des petits panneaux qu’on peut déplacer d’une chambre à l’autre à volonté, certains occupants peuvent changer sans toucher à ce panneau et d’autres occupants ne peuvent pas changer sans détruire toute la chambre et en construire une autre (en faisant suivre le panneau ou non). Ah, et les chambres peuvent changer de place toutes seules. Évidemment, ça rend l’analogie beaucoup moins utile, et surtout ce serait rentrer dans un niveau de détail trop grand trop tôt. Éviter les analogies foireuses et se contenter de dire que déclarer une variable en Python veut juste dire mettre une étiquette sur une valeur me parait plus simple, et surtout moins faux.

On peut effectuer trois principales opération avec une variable :

  • la déclarer (=la créer)
  • lui affecter une valeur (=changer l’occupant de la chambre)
  • utiliser sa valeur (=récupérer une copie de l’occupant actuel de la chambre)

Faut faire gaffe avec l’utilisation du mot copie. En Python, les variables sont plutôt des références vers les PyObject. Selon leur mutabilité et la façon dont ces "références" sont capturées, ça peut conduire à des choses bizarres.


Un itérateur, quand à lui, est une variable dont la valeur change à chaque tour de boucle

Heu non… Un itérateur est un objet qui se charge de traverser un itérable. C’est lui qui s’occupe de se rappeler où on en est dans l’itérable, et de produire les éléments les uns après les autres. Dans la boucle for i in range(5), l’itérable est range(5), l’itérateur est un objet qu’on ne manipule pas directement mais qu’on pourrait créer avec iter(range(5)) et i prend les valeurs des éléments "contenus" dans le range. De manière plus générale, un Iterable est un objet qui implémente __iter__(self) -> Iterator[T], et un Iterator[T] est un objet qui implémente __next__(self) -> T (et diverge avec l’exception StopIteration).

Mais ce que je voulais surtout dire à part ce point de sémantique est que toute cette partie sur les boucles et les itérateurs est beaucoup trop rapide pour être compréhensible par quelqu’un qui découvre la programmation. Tu présentes while relativement lentement, avec un petit exemple, puis tout le reste est très rapide en comparaison. C’est dommage parce que la notion d’itérable en Python est très souvent utilisée, donc ça vaut le coup de prendre bien le temps de l’expliquer, notamment en insistant sur les contrats qu’elle implique (ce qui nécessite de pas se planter sur ce qu’est un itérateur). Ça peut être plus loin dans le tutoriel bien sûr, mais là en l’état c’est trop tôt et trop court pour être utile au lecteur.


Troisième exemple, toute la partie sur la présentation de ce qu’est la POO et de l’héritage. À ta décharge, c’est un truc qui est très mal expliqué (et probablement encore plus mal compris) un peu partout. Tu tombes dans l’erreur classique de tenter de donner un exemple de la vie de tous les jours (ici Animal > Humain > {Homme, Femme}) pour expliquer ce que sont des classes et aussi pour expliquer l’héritage. Si ça peut aider à comprendre certaines choses dans certains contextes, ça empêche complètement de comprendre beaucoup de choses plus fondamentales parce que l’exemple est beaucoup trop artificiel :

  • à quoi sert concrètement la POO dans un problème de programmation concret (i.e. c’est un moyen d’abstraction) ;
  • comment modéliser correctement un problème donné pour ne pas que la complexité du programme et de l’API explose en vol (les principes SOLID et autres considérations de software design en POO) ;
  • comment utiliser la composition à bon escient pour bien partager les responsabilités ;
  • pourquoi l’héritage est (ironiquement) l’une des pires façon de modéliser un problème du genre Animal > Humain > {Homme, Femme}, et de réutiliser du code en général ;
  • dans le cadre de Python, comment l’héritage et les ABC d’une part et les protocoles d’autres part permettent d’écrire du code polymorphique sans se perdre dans les différents contrats à respecter.
+3 -0

Bonjour,

Merci infiniment pour toutes vos remarques constructives !

Pour ce qui est des variables, je me demande si l’analogie d’une "boite" portant une étiquette serait plus juste…

Je vais voir comment je peux reprendre la partie sur les itérateurs/itérables pour qu’elle soit plus juste et explicative (il me parait quand même utile d’aborder le sujet des itérateurs lorsque l’on parle des boucles "for", mais je me trompe peut-être…).

Pour ce qui est de la POO, est-ce que l’exemple d’une classe Client (pour un site de vente, par exemple) serait plus pertinent ?

Merci beaucoup,

@flopy78

Bonjour,

Conformément à vos suggestions, je vais entamer un nouveau tutoriel qui se concentrera su la gestion et le traitement de fichiers (partie III de mon tutoriel actuel). En effet, le tutoriel "un zeste de Python" ne semble pas parler des modules os et panda, qui sont pourtant centraux dans ce domaine. Je compte aussi reprendre d’autres éléments déjà présents dans ce tuto, comme les images (avec Pillow) et les formats de stockage textuels (.csv, .json, .xml)…

Avant de me lancer dans ce projet, j’aimerais avoir votre avis sur ce que j’ai déjà écrit sur ce sujet dans la partie III.

Merci d’avance,

@flopy78

Pour ce qui est des variables, je me demande si l’analogie d’une "boite" portant une étiquette serait plus juste…

Mon opinion personnelle est qu’il n’y a pas besoin d’une analogie pour présenter les variables, et que c’est même non souhaitable parce qu’une analogie peut introduire un mauvais modèle mental. Les variables en Python sont plus compliquées qu’il n’y parait en premier abord parce que ce sont presque des références partagées, mais elles ne se comportent pas toujours comme telles à cause du modèle biscornu de mutabilité de Python. Je pense qu’il est préférable de les introduire simplement comme un nom qu’on donne à une valeur (même si c’est un tout petit peu faux), puis étoffer ensuite l’explication au-fur-et-à-mesure que les cas se présentent pour dire

  • qu’on peut déplacer le nom sur d’autres valeurs à volonté ;
  • qu’on peut avoir plusieurs noms sur la même valeur ;
  • ce qui se passe avec les types mutables vs immuables.

Une fois que tout ça est montré, on peut alors clairement exposer l’idée que ce sont des étiquettes sur des object et les conséquences surprenantes que ça peut avoir.

il me parait quand même utile d’aborder le sujet des itérateurs lorsque l’on parle des boucles "for", mais je me trompe peut-être…

Dire que for permet de traverser un itérable, ça parait pas mal pour introduire la terminologie. Mais là en l’état, soit tu en dis trop soit pas assez sur les itérateurs pour que ce soit clair et utile, et je pense qu’il est trop tôt pour en dire plus. Quand tu as déjà introduit d’une part la notion un peu floue qu’on peut traverser des collections (comme les listes et les dictionnaires) et d’autres objets (comme les ranges) dans les boucles for, et d’autre part que tu as présenté l’idée que les classes définissent le comportement des objets, tu as tout ce qu’il faut pour introduire la notion d’itérables et d’itérateurs comme des interfaces.

Pour ce qui est de la POO, est-ce que l’exemple d’une classe Client (pour un site de vente, par exemple) serait plus pertinent ?

Tu prends le problème par le mauvais bout, je pense. Plutôt que prendre un truc qui ressemble vaguement à quelque chose qui pourrait se représenter par une classe et inventer un problème flou autour, prend un problème concret avec une solution impérative un peu naïve, et montre comment introduire des classes permet de gérer la complexité du problème de manière plus flexible. Je pense qu’il est important de montrer que la POO est juste une façon de modéliser les problèmes avec des classes et des interfaces plutôt que de partir des classes et les présenter comme solutions à des problèmes inexistants.

EDIT : je viens de voir que tu vas réduire le champ du tuto, j’ai pas encore regardé la partie 3.

+0 -0

Bonjour,

Merci infiniment pour toutes ces précisions.

Je me demande si la modélisation des éléments graphiques (balle, personnage…) dans un jeu vidéo pourrait être un exemple de problème concret à même d’introduire la POO…

J’aimerais aussi avoir ton avis sur une autre analogie que je souhaiterais employer : la comparaison de la structure en arborescence de la mémoire avec l’organisation d’une grosse ville en arrondissements, quartiers, pâtés de maisons, rue, numéro de rue…

Bonne journée,

@flopy78

Conformément à vos suggestions, je vais entamer un nouveau tutoriel qui se concentrera su la gestion et le traitement de fichiers (partie III de mon tutoriel actuel).

flopy78

Ah je venais justement de terminer ma relecture des parties I et II (pas encore eu le temps d’attaquer la III). Afin que ce ne soit pas perdu je le mets quand même en bloc secret dans ce post :

Dans l’ensemble le cours me semble plutôt correct et les analogies amusantes (quand elles tiennent la route), c’est intéressant de présenter les notions dans cet ordre (fonctions avant les autres structures logiques) mais est-ce pertinent ? Quel est le but de cette approche ?

Introduction

  • Je la trouve un peu brute, elle n’explique pas à quoi sert de programmer / apprendre Python ?

Les outils pour programmer confortablement

  • Le chapitre parle de l’installation d’un IDE mais pas de Python lui-même il me semble (ou alors c’est inclus avec l’éditeur ?)
  • Ne devrais-tu pas ajouter un lien vers la doc Python ?
  • Je dirais que python.doctor est plutôt une ressource à déconseiller pour l’apprentissage de Python
  • Pour ce qui est de w3schools je ne connais pas mais ça n’a pas l’air terrible non plus

Quelques notions indispensables

  • Les exemples sont plutôt pertinents
  • les triple-quotes ne permettent pas d’insérer des commentaires, ils forment des chaînes de caractères à part entière
    >>> [
    ...     1,
    ...     2,
    ...     '''
    ...     Ceci est un commentaire
    ...     '''
    ... ]
    [1, 2, '\n    Ceci est un commentaire\n    ']
    
  • Donc les lignes en question sont parfaitement lues par l’interpréteur (et heureusement)
  • Concernant les erreurs, l’interpréteur Python affiche même maintenant explicitement l’emplacement de l’erreur sur la ligne

Les données

  • Attention 2+9/3 renvoie un flottant contrairement à ce qui est dit au départ
  • True et False sont traduits en 1 et 0 et non 0 et 1.
  • L’exemple not True and True illustre assez mal les priorités puisque le résultat est le même avec not (True and True)
  • L’exercice sur les boules blanches/noires est un peu alambiqué, je n’ai pas compris du tout ce qui était attendu comme résultat
  • « on utilise le signe + pour concaténer deux nombres. », tu es sûr de parler de concaténation ?
  • De la même manière que ''' il existe aussi """

Le stockage de données

  • +1 à adri1 sur les variables, la métaphore est trompeuse et passe à côté du fonctionnement des variables en Python : comment dans ton modèle représentes-tu le fait que deux numéros amènent à la même chambre ? Ou qu’un numéro se déplace de chambre en chambre ?
  • Il n’y a pas vraiment en Python de notion d’allocation mémoire, donc pas de variable à déclarer ni de « chambre » à réserver
  • Les constantes en Python ne sont qu’une convention, rien n’interdit de réaffecter une variable NOM à une autre valeur
  • Tes commentaires sur l’exemple d’utilisation des listes sont assez longs et n’apportent rien de plus que la sortie de la console
  • Tu montres la modification des éléments d’une liste sans en parler, on pourrait croire que cette opération existe aussi sur les strings
  • Tu dis que comme pour les chaînes de caractères il n’est pas possible d’utiliser % sur des listes. C’est vrai pour les listes mais pas pour les strings
  • True in [1,2,3] vaut True contrairement à ce que tu écris
  • À quoi servent les \ dans ton exemple sur les listes multi-dimensionnelles ? Ils ne sont pas nécessaires pour revenir à la ligne
  • Les tuples ne se définissent pas à l’aide de parenthèses (sauf ()) mais à l’aide de virgules, les parenthèses sont là uniquement pour une question de priorités
  • Tu dis qu’on ne peut pas concaténer les ensembles, il existe tout de même l’opérateur | qui réalise une union, ce qui correspond plus ou moins à la même chose

Les fonctions

  • Contrairement à ce que tu sembles dire int("3.5") n’est pas une conversion valide
    >>> int("3.5")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: invalid literal for int() with base 10: '3.5'
    
  • Les sets ne sont pas spécialement ordonnés par ordre croissant lorsque convertis en liste, c’est aléatoire suivant l’état de l’interpréteur
    >>> list({10, 20, 30, 40})
    [40, 10, 20, 30]
    
  • Il est faux de dire que l’ordre des éléments d’une liste convertie en ensemble puis à nouveau en liste est conservé
    >>> list(set([10, 20, 30, 40]))
    [40, 10, 20, 30]
    
  • Tu parles de la fonction exe, il s’agit d'exec
  • Tu confonds les termes d’arguments et de paramètres quand tu parles de définir « la fonction somme avec deux arguments a et b »
  • On peut parfaitement placer un paramètre « normal » après *args, c’est simplement qu’il ne pourra pas recevoir d’argument positionnel
  • N’est-il pas un peu tôt pour aborder les générateurs ?
  • Ce n’est pas vraiment la fonction qui est un générateur, mais ce qu’elle renvoie
  • map ne renvoie pas à proprement parler un générateur, même si le principe est similaire
  • À propos de la portée des variables, tu dis que la variable x définie ligne 1 n’est pas accessible depuis la fonction, ce qui est faux, il n’est juste pas possible de la réassigner depuis la fonction
  • Je pense que ce n’est pas le moment pour parler de global qui induit bien souvent les débutant·e·s en erreur
  • Tu dis de ne jamais placer de paramètre optionnel avant un obligatoire, c’est pourtant possible sous certaines conditions (si le paramètre ne peut recevoir que des arguments nommés)

Pause pratique : une petite calculette (partie 1)

  • Pourquoi ne mets-tu pas en forme les exemples de façon à mieux comprendre ce qui est tapé par l’utilisateur (en plaçant ça derrière >>> ) ?
  • Ce qui est attendu comme réponse n’est pas clair du tout

Les conditions

  • Tu présentes comme un problème le fait que les opérateurs booléens (and / or / not) puissent recevoir des valeurs non booléennes, ce n’est pas du tout un soucis
  • Ta fonction is_majeur n’a pas besoin de bloc if, elle peut simplement se résumer en un return age >= AGE_MAJORITE qui serait plus clair
  • Dans un exemple tu écris « code à exécuter si condition1 et condition4 sont vraies » alors que condition1 doit être fausse pour mener à cet embranchement
  • Pour revenir à la ligne dans une condition, il est parfois préférable d’utiliser des parenthèses que des backslash

Les boucles

  • Tu présentes la boucle infinie comme dangereuse et pouvant faire planter la machine. Ta boucle s’interrompt à chaque itération pour demander une saisie à l’utilisateur donc le programme peut être coupé à tout moment sans problème
  • Le in de la boucle for n’a rien d’un test de condition, il sert juste de délimiteur dans cette construction
  • Tu confonds en effet les notions d’itérateur et de valeur renvoyée par l’itérateur à chaque étape
  • Tu utilises le flag de formatage %s pour insérer des nombres dans des chaînes, c’est un peu étrange (et ça faudrait le coup d’aborder les autres méthodes de formatage, notamment les f-strings)
  • range n’est pas à proprement parler un générateur même si ça s’en rapproche

Pause pratique : une petite calculette (partie 2)

  • Il y a des méthodes plus efficaces pour calculer le PGCD/PPCM que d’itérer sur tous les nombres
  • Pourquoi ne pas utiliser un range avec un pas négatif ?
  • Tu écris « 4 3 2 * 1 = 24 »
  • Pourquoi noter la factorielle !26 plutôt que 26! ?"
  • L’exercice sur le parsing de l’entrée pour identifier les factorielles est vraiment alambiqué et la solution donnée ne fonctionne pas

Les modules

  • random.choice n’accepte pas un itérable mais un subscriptable, random.choice appliqué sur un ensemble ne fonctionne pas par exemple
  • Tu pourrais présenter les fonctions math.gcd et math.lcm puisque tu les as fait implémenter au chapitre précédent
  • Pourquoi qualifies-tu math.floor de défaut ?
  • Pour mesurer un temps d’exécution on préférera time.monotonic() à time.time() pour éviter tout effet extérieur sur l’écoulement du temps
  • L’explication concernant les packages est assez brève et ne permet pas vraiment de comprendre

La Programmation Orientée Objet (POO)

  • L’analogie avec les êtres humains n’est pas très bonne, ça ne reflète pas les cas d’usage réels
  • Sans parler du fait que les attributs décrits ne correspondent pas forcément à la réalité des choses (femmes à barbe, hommes sans barbe, handicapés qui ne veut pas dire en incapacité de marcher, personne « valide » plutôt que « saine »)
  • Plusieurs des exemples donnés comportent des erreurs à l’exécution (variables inexistantes)
  • Les explications sur super peuvent être trompeuses, la fonction ne référence pas forcément le parent direct puisqu’elle s’occupe de résoudre la hiérarchie des parents
  • Les entiers et les booléens ont eux aussi des attributs/méthodes qui peuvent être utiles pour certains usages
  • Il n’est pas impossible de nommer une variable str, c’est simplement déconseillé

La gestion d’erreur

  • La syntaxe except ModuleNotFoundError,AttributeError: n’est plus valide en Python
  • L’intérêt de finally est d’exécuter du code dans tous les cas, qu’il y ait eu une erreur ou non
  • La classe Exceptions n’existe pas, il s’agit d'Exception
  • Il n’est pas utile de définir __init__ dans une classe si c’est juste pour appeler super().__init__

Pause pratique : une petite calculette (partie 3)

  • L’algorithme de la solution est à nouveau très tordu, difficile de le suivre et propice aux bugs, pourquoi avoir besoin de tester spécifiquement la lettre p par exemple ?
  • Quant au second exercice, évite vraiment d’aller modifier à la main locals(). Si tu as besoin d’un dictionnaire associant des valeurs à un nom, alors ajoute un tel dictionnaire.

En effet, le tutoriel "un zeste de Python" ne semble pas parler des modules os et panda, qui sont pourtant centraux dans ce domaine. Je compte aussi reprendre d’autres éléments déjà présents dans ce tuto, comme les images (avec Pillow) et les formats de stockage textuels (.csv, .json, .xml)…

flopy78

Pour ce qui est du module os il y est bien abordé par contre en effet pandas est hors du scope du tutoriel (qui ne prétend couvrir que Python, pas les nombreux modules complémentaires existants — à ce propos je ne pense d’ailleurs pas qu’on puisse qualifier pandas de plus central qu’un autre).

Je me demande si la modélisation des éléments graphiques (balle, personnage…) dans un jeu vidéo pourrait être un exemple de problème concret à même d’introduire la POO…

Ce qui compte, c’est pas tant l’exemple précis qui sera utilisé, mais plutôt la présentation.

J’aimerais aussi avoir ton avis sur une autre analogie que je souhaiterais employer : la comparaison de la structure en arborescence de la mémoire avec l’organisation d’une grosse ville en arrondissements, quartiers, pâtés de maisons, rue, numéro de rue…

Après avoir jeté un œil à la partie 3 de ton tuto, j’imagine que tu veux parler ici de l’arborescence des fichiers telle qu’exposée par le système de fichiers plutôt que l’organisation de la mémoire. J’ai deux choses à dire à ça.

  • Je suis pas convaincu que ce soit une bonne analogie, parce que la topologie est tout de même assez différente. Dans une ville, tu as une ville qui contient des arrondissements, qui contiennent des quartiers, qui contiennent des rues, qui contiennent des bâtiments, qui contiennent des appartements. Tu as 5 niveaux à ton arborescence, chacun correspondant à un type de nœud. Les rues sont toujours le niveau 3, et les appartements sont toujours le niveau 5. La largeur et la profondeur de l’arbre sont aussi relativement similaires. C’est une structure assez rigide. A contrario, dans un système de fichiers, tu as seulement deux types de "nœuds", les dossiers et les fichiers simples (les feuilles de l’arborescence). Les dossiers contiennent d’autres nœuds. Les fichiers simples peuvent être trouvés à n’importe quelle profondeur, et la largeur et profondeur de l’arbre peuvent varier énormément. Je pense que dire qu’un fichier simple est une chemise avec des feuilles dedans, et que les dossiers sont des boites qui peuvent contenir d’autres boites et des chemises serait déjà plus proche. Bon, tu as après le problème que les liens sont pas modélisables facilement avec cette analogie… Pour être franc, je suis pas forcément fan des analogies un peu simplistes qu’on trouve dans beaucoup de tutos pour débutants. Un schéma qui montre comment les choses s’organisent accompagné de texte explicatif sans chercher à faire de parallèle à autre chose me parait plus robuste. Surtout que c’est facile de le faire aussi simple ou complexe que l’on veut et l’enrichir au besoin, alors que tu peux te retrouver bloqué par une analogie mal choisie.
  • Tu parles d’organisation de la mémoire comme si c’était comme ça que les choses étaient organisées pour le matériel. En vrai, toute l’arborescence de fichiers est une abstraction gérée par le système de fichiers, et n’est absolument pas le reflet de l’organisation des fichiers sur le disque physique. Rentrer dans ces détails est évidemment en dehors du cadre de ce tuto, mais j’attire juste ton attention sur le fait que le niveau d’abstraction du discours est assez déroutant : tu parles de registres (qui sont une considération matériel très bas niveau), et un paragraphe plus loin tu parles d’une arborescence exposée par un système de fichiers.

Tiens au passage, je comprends pas trop pourquoi tu parles de registres (surtout dans un paragraphe sur les fichiers !). C’est vraiment le truc dont on est à des années-lumières de se préoccuper quand on code en Python (au pire du pire, on peut commencer à se préoccuper des tailles de caches/nœuds NUMA si on fait des gros traitements avec numpy et qu’il faut découper le calcul intelligemment, mais ce sont des considérations qui n’inquiètent pas le débutant). Là j’ai l’impression que ce qui t’intéresse, ce serait plutôt de parler de mémoire volatile (celle utilisés jusqu’à présent) vs mémoire de stockage (là on va pouvoir préserver de l’information même en mettant l’ordinateur hors-tension).


Pour commenter un peu sur les explications sur Python dans ton tuto, il y a encore plusieurs choses qui m’interpellent. Je ne mets que les points principaux.

  • Utiliser with n’est pas pour s’éviter d’avoir à appeler close à la main, c’est pour assurer que close soit toujours appelé même si le flux d’exécution est interrompu (par un return ou une exception, par exemple), et donc appeler open à nu comme tu le fais est une mauvaise pratique ;
  • Appeler eval pour lire des fichiers texte (notamment json) est une aberration. Les modules standards (comme… json) font le taf mieux et plus rapidement, en offrant des abstractions pour lire et écrire qui sont beaucoup plus robuste. Sans compter qu'eval est une faille de sécurité béante puisqu’elle permet d’injecter du code arbitraire.
  • L’explication sur "les données binaires" (dans la partie sur les fichiers textes ???) est très bizarre. Quand on parle de données binaires, on ne parle pas du tout d’écrire une chaîne de caractère avec la représentation binaire sortie par bin(nombre) comme tu sembles l’entendre. Là, ce dont tu parles est juste du formatage de texte. Quand on parle d’écrire des données binaires, on parle d’écrire les bytes qui représentent la valeur manipulée directement (ce que fait pickle) plutôt qu’écrire les bytes qui représentent une représentation textuelle de la valeur manipulée.
  • Il semblerait que tu vas parler du module os, mais pas du module pathlib. Celui-ci est l’abstraction à préférer pour des opérations sur les chemins, les abstractions offertes dans os.path n’étant pas très bien faites.
  • Je ne sais pas trop si l’énumération de formats que tu fais est très pertinente. Il est plus important d’avoir le réflexe de chercher des modules standards, ou si nécessaire des dépendances externes, qui font le boulot pour nous quand on croise un format quelconque. Il me parait plus utile d’insister sur les abstractions offertes par la lib standard pour les chemins (pathlib, donc) et les opérations diverses qu’on peut avoir besoin de faire dessus. La lecture et la manipulation des données est presque un non-problème en Python parce qu’il existe des libs pour l’énorme majorité des formats qu’on peut croiser.
+0 -0

Bonjour,

Merci pour vos précisions.

J’ai bien conscience qu’il n’est pas bon de s’habituer à appeler open à nu, mais je trouve que ça permet de bien comprendre comment elle fonctionne dans un premier temps…

Dans le nouveau tutoriel plus restreint que je suis en train de développer, je penserais à ajouter la nuance que vous m’avez décrite sur with

Je veillerais désormais à utiliser les modules de lecture plutôt que eval, pour éviter les problèmes de sécurité (je dois avouer que je n’y avait pas du tout pensé :B )…

Merci aussi pour la référence vers le module pathlib…

Les "registres" me viennent d’un tutoriel Zeste de Savoir sur le C dans lequel le fonctionnement des mémoires de l’ordinateur est expliqué (ici).

Bonne soirée,

@flopy78

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte