Si vous ne savez pas ce que contient une variable, vous ne comprenez pas le programme


L’immense majorité des questions qu’on me pose sur le fonctionnement d’un programme (ou sur des détails dans les tutos) peut être résolu d’une seule manière.

En sachant ce qu’il y a dans les variables.

Un ordinateur est une machine à états. Les variables représentent cet état. Le seul moyen de comprendre ce que fait un programme, c’est de savoir à quel moment il est dans quel état.

Quand vous ne comprenez pas ce que fait un programme, la première et plus importante question à vous poser et donc :

Que contient cette variable ?

Répondre à la question

La beauté de Python, c’est qu’il vous permet de très facilement répondre à cette question par vous même. Tout ce que vous avez à faire c’est copier le code, le mettre dans un fichier (ou un shell), et le lancer.

Ne restez pas passif devant un tuto. Vous n’en comprendrez que la moitié (au mieux).

Un tuto, une doc, un cours, un snippet ne se lit pas, il se travaille.

Voici tout ce que vous pouvez faire à une variable pour obtenir des informations sur elle :

>>> i = 1
>>> print(i) # afficher la variable
1
>>> print(type(i)) # afficher son type
<type 'int'>
>>> print(i.__class__) # afficher la classe dont elle est issue
<type 'int'>
>>> print(i.__class__.__name__) # affiche le nom de sa classe
>>> print(dir(i)) # afficher les méthodes de cet objet
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
>>> help(i) # aide sur cet objet
Help on int object:
 
class int(object)
 |  int(x[, base]) -> integer
 |  
 |  Convert a string or number to an integer, if possible.  A floating point
 |  argument will be truncated towards zero (this does not include a string
 |  representation of a floating point number!)  When converting a string, use
 |  the optional base.  It is an error to supply a base when converting a
 |  non-string.  If base is zero, the proper base is guessed based on the
 |  string content.  If the argument is outside the integer range a
 |  long object will be returned instead.
 |  
 |  Methods defined here:
 |  
 |  __abs__(...)
 |      x.__abs__() <==> abs(x)
...

Ces informations répondent à la question “qu’est-ce que c’est”, “comment c’est configuré” et “qu’est-ce que ça peut faire”.

C’est très important. Vous ne pouvez pas comprendre ce que fait un programme sans ces informations.

En Python une variable peut contenir n’importe quoi

J’ai dis n’importe quoi.

Pas juste les types de base :

>>> i = 'a'
>>> type(i)
<type 'str'>
>>> i = {}
>>> type(i)
<type 'dict'>
>>> i = []
>>> type(i)
<type 'list'>

Ni même juste des résultats de fonctions :

>>> i = test()
>>> type(i)
<type 'int'>

Non. Les variables Python peuvent contenir les fonctions elles-même !

>>> type(test)
<type 'function'>
>>> i = test
>>> i()
1
>>> type(i)
<type 'function'>

Et là ça devient important de savoir de quoi on parle :

>>> i.__name__
'test'

Mais les variables peuvent aussi contenir des instances de vos classes :

>>> class Essai(object):
...     pass
... 
>>> i = Essai()
>>> type(i)
<class '__main__.Essai'>

Sauf que les variables peuvent aussi contenir les classes elles-même !

>>> type(Essai) # les classes sont de type 'type'. Funky !
<type 'type'>
>>> i = Essai # ceci n'est PAS une instance. Ce n'est PAS Essai().
>>> type(Essai)
<type 'type'>
>>> i.__class__
<type 'type'>
>>> i.__name__
'Essai'

Les fonctions et les classes ne sont pas juste des noms en Python. Ce sont des choses que vous pouvez manipuler. Donc on les retrouve dans des variables.

Donc vous n’avez pas le choix. Vous devez savoir de quoi on parle. Et il faut donc bien comprendre ce qu’est un type, et qu’est-ce qui est de quel type :

>>> type(str) # str est une classe
<type 'type'>
>>> type(str()) # le résultat de l'appel de str est une string
<type 'str'>
>>> type(Essai) # Essai est une classe
<type 'type'>
>>> type(Essai()) # le résultat de l'appel de Essai est un objet Essai
<class '__main__.Essai'>
>>> type('1') # '1' est une string
<type 'str'>
>>> type(1) # 1 est un int
<type 'int'>
>>> type(True)
<type 'bool'> # True est un boolean

Si vous ne comprenez pas les types, vous ne pouvez PAS comprendre un programme.

Ce n’est pas honteux. Arrêtez d’essayer un truc impossible, c’est tout. Revenez en arrière. Allez apprendre ce qu’est un type x ou z.

Puis retournez essayer de comprendre le programme.

Il n’y a PAS d’alternative.

Quand vous lisez un programme, vous devez savoir ce qu’il y a dans une variable :

  • quel est son type ?
  • quelle est sa valeur ?
  • qu’est-ce que je peux faire avec (méthodes, attributs, etc) ?

Pdb à la rescousse

Donc quand vous lisez un tuto, vous allez copier / coller du code. Vous allez le lancer. Si vous ne le faites pas, vous ne comprendrez pas.

Maintenant, dans un premier temps vous allez utiliser des print.

print type(truc)
print truc.__class__
print dir(truc)

Et pour les fonctions et les classes :

print truc.__name__

Mais on peut faire mieux. Utilisez le debugger de Python intégré : PDB. J’ai écrit un bon article sur la question, mais pour résumer, quand vous voulez avoir des informations sur une variable dans un programme, juste avant la variable faites :

import ipdb; ipdb.set_trace()

Puis lancez le programme. Un shell va s’ouvrir, bloquant le programme à cet endroit. Et vous pourrez manipuler la variable à ce moment du programme.

Pour quitter, entrez q.

11 thoughts on “Si vous ne savez pas ce que contient une variable, vous ne comprenez pas le programme

  • Krysztof von Murphy

    Y a des jours où je me dis que j’ai eu du bol d’avoir été formé à l’ancienne avec un langage très fortement typé (Turbo Pascal, non c’est pas neuf). Avec les langages modernes on ne sait parfois plus trop ce qu’on manipule…

  • roro

    @Krysztof von Murphy:
    Tu l’as dit, on est carrément dans la 9 ième dimension. Mais la puissance du truc fait rêver.
    Tant que j’y suis j’ai une question: Quelqu’un connait-t-il: ” Visustin” un soft qui donne l’organigrammes du code ? Et existe-il autre chose dans le genre ?

  • Epychoc

    Merci pour cet article à l’apparence bidon mais non moins important.
    C’est cool, je viens de capter l’existence de PDB … mais pourquoi utiliser Python 2 ?

  • roro

    @Sam:
    Il vaudrait peut-être mieux mettre les “print” en commande (sans les chevrons) et leur résultat en #
    Il a l’air de manquer “:” à class int(object)
    Bref, rendre le truc fonctionnel.

  • Sam Post author

    J’étais parti pour écrire un commentaire expliquant que c’était parfaitement incongru et inutile, mais je réalise que c’est moi qui ai tord.

    Effectivement, je peux voir l’attrait pour un lecteur d’avoir ce format.

    Ca fait chier car c’est plus de boulot.

    Bon, je vais pas réécrire cet article, mais je vais essayer pour les prochain de suivre le format dont tu parles.

    (par contre le class int(object) est un truc généré par l’aide de Python, il manque rien)

  • roro

    Si c’est plus de boulot, laisse comme ça. C’est pas bien grave.
    J’ai vu que tu utilisais “dreampie” pour élaborer. je présume que c’est pour la mise en html ?
    Si tu écrit ton code dans un éditeur, et que pour le mettre sur le site, tu te place côté client; en utilisant les balises code, tu dois pouvoir faire un simple copié/collé. non ?
    Haaargh… Mais je suis con! ton code, il va aller dans les commentaires!!!

  • Sam Post author

    Je pense que je vais maintenant écrire les tutos avec reinteract (le truc que m’a montré Kontre). Ca devrait me permettre de faire ce que tu demande sans trop de boulot. Si ça se trouve, je peux même suggérer un patch ou un plugin pour automatiser le truc.

  • Pascal

    C’est marrant, je lis les articles et les commentaires de ce blog et je me dis :”Purée, c’est des bêtes ces mecs en Python.” Ben oui, pour certains articles j’ai vraiment pas le niveau…
    Au niveau du code, la moindre erreur syntaxique est repérée immédiatement par un lecteur. Par contre au niveau de l’orthographe, là vous êtes moins fortiches ! “j’ai tord” pour “j’ai tort”, je ne parle même pas des accords de verbes…
    Dans le fond, c’est pas grave. C’est juste que je dois être frustré de pas pouvoir dire quelque chose d’intelligent à propos des articles. Alors je charrie un peu…
    Bon bref, tout ça pour dire que je trouve ce blog bien sympa et très instructif (pour les parties qui me sont accessibles !).
    Bonne Année 2014 !

  • Sam Post author

    Tu amélioreras ton Python plus vite qu’on améliorera notre orthographe :-)

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.