PROJET AUTOBLOG


Sam et Max

source: Sam et Max

⇐ retour index

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

mardi 12 février 2013 à 14:41

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 :

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.

flattr this!