Valeurs, expressions et variables ================================= .. index:: capacité Dans ce chapitre, nous décrivons les opérations de bases supportées par le langage Python (ce que nous avons appelé précédemment les « capacités » de l'ordinateur). Fondamentalement, un ordinateur sert à effectuer des *calculs*, mais on va voir que ce terme est à prendre au sens large. Après avoir présenté les types de valeurs supportés par Python et les calculs qu'il peut effectuer avec ces valeurs, on verra comment les résultats de ces calculs sont stockés dans la mémoire de l'ordinateur. Rappelons encore que ce cours n'est pas un cours de Python. La présentation ci-dessous ne présente pas le langage Python de manière exhaustive. Elle vise seulement à fournir les bases qui nous permettront d'écrire des algorithmes. .. index:: ! expression Valeurs et expressions ++++++++++++++++++++++ Dans cette section, nous présentons les valeurs que nous allons utiliser dans nos algorithmes, et les calculs possibles sur ces valeurs. Nous regroupons sous le terme **expression** les valeurs simples et les calculs plus ou moins complexes. Tous les exemples d'expressions de cette section peuvent être tapés directement dans un interpréteur Python qui affichera le même résultat. .. index:: entier, int single: nombre; entier Nombres entiers --------------- Python supporte, comme tous les langages de programmation classiques, le calcul sur les nombres entiers (en anglais : *integer*, souvent abrégé ``int`` en informatique). Un nombre entier s'écrit comme une série de chiffres, éventuellement précédée par un signe (``+`` ou ``-``). Par exemple : ``0``, ``42``, ``+123`` et ``-987654`` sont des entiers. Python supporte les opérations arithmétiques usuelles sur les entiers :: >>> 10+3 # addition 13 >>> 10-3 # soustraction 7 >>> 10*3 # multiplication 30 >>> 10//3 # division entière 3 >>> 10%3 # modulo 1 >>> 10**3 # puissance 1000 Notez que le modulo est l'opération qui permet de calculer le reste de la division euclidienne (ou division entière). Par exemple, ``9%2=1`` car ``9 = 2*4 + 1``, ``4`` étant la valeur obtenue par la division entière ``9//2``. Ces opérateurs peuvent bien sûr être combinés. Python respecte les règles de priorité habituelles entre opérateurs, et autorise l'utilisation des parenthèses pour les surcharger. Les espaces peuvent aussi être utilisés pour améliorer la lisibilité :: >>> 5+4*3**2 41 >>> 5 + 4 * 3**2 41 >>> ((5+4)*3)**2 729 >>> ((5+4) * 3)**2 729 Pour mémoire, il existe un ordre de priorité entre les opérateurs arithmétiques : les parenthèses sont les plus prioritaires, viennent ensuite les exposants, la multiplication et la division, puis l'addition et la soustraction. Il en va de même pour les opérateurs booléens_ : le plus prioritaire est la négation, suivi du ``et`` puis du ``ou``. N'hésitez pas à utiliser les parenthèses pour forcer les priorités et rendre vos algorithmes plus lisibles ! Notons quelques spécificités de Python qui le distinguent d'autres langages de programmation (comme C ou Java) : * L'opérateur de division entière ``//`` est différent de l'opérateur de division réel ``/`` (qu'on présentera dans la section suivante). Dans d'autres langages [#div-entière]_, il n'existe souvent que l'opérateur ``/`` et c'est le contexte qui détermine le type de division qu'il représente. Le fait d'avoir deux opérateurs distincts améliore la lisibilité des programmes. * Alors que dans la plupart des langages de programmation, les entiers sont limités en taille, Python peut faire des calculs sur des entiers arbitrairement grands (pour s'en convaincre, on pourra taper ``123**456``). Si cela entraîne de moins bonnes performances, cela permet en revanche de se focaliser sur les aspects algorithmiques et calculatoires, en s'affranchissant des limites imposées par d'autres langages. .. index:: flottant, float single: nombre; flottant single: nombre; à virgule flottante Nombres flottants ----------------- Au delà des entiers, les ordinateurs sont capables de représenter des nombres à virgule. Ils utilisent pour cela un système nommé *nombre à virgule flottante* ou encore *nombre flottant*, ou tout simplement *flottant* (en anglais : *floating point number*, souvent abrégé ``float`` en informatique). Sous leur forme la plus simple, les flottants sont composés d'une partie entière composée de chiffres, suivie du point décimal ``.``, suivi d'une partie décimale composée de chiffres, le tout éventuellement précédé d'un signe ``+`` ou ``-``. Par exemple : ``0.0``, ``4.2``, ``+12.3``, ou ``-987.654`` sont des flottants. Mais ils peuvent également être suivis d'un exposant, formé par la lettre ``e`` suivi d'un nombre entier. Cette notation correspond à la notation scientifique (le ``e`` signifiant « multiplié par 10 puissance... »). Par exemple, ``1e2`` équivaut à ``100.0``, ``-3.4e+5`` équivaut à ``-340000.0``, et ``6.7e-8`` équivaut à ``0.000000067``. Là encore, Python supporte les opérations arithmétiques de base sur les nombres flottants :: >>> 2.5 + 1.5 # addition 4.0 >>> 2.5 - 1.5 # soustraction 1.0 >>> 2.5 * 1.5 # multiplication 3.75 >>> 2.5 / 1.5 # division réelle 1.6666666666666667 >>> 2.5 ** 1.5 # puissance 3.952847075210474 Notons que toutes ces opérations (y compris la division réelle) peuvent combiner entiers et flottants, mais le résultat sera alors toujours un flottant. .. NB: ce qui suit est une considération de programmation, pas d'algorithmique, donc je l'ai viré. Je voulais le mettre notamment pour dire que la division réelle pouvait Le résultat de la division réelle est toujours un flottant, même quand ses deux opérandes sont des entiers. Cela peut avoir une incidence car, contrairement aux entiers, les flottants ont une taille limitée, et les calculs sur les flottants sont sujets à des approximations :: >>> 1.5 + 1.5 3.0 >>> 10 * 0.5 5.0 >>> 10 / 2 5.0 >>> 10 / 3 3.3333333333333335 .. index:: booléen, bool, True, False Booléens -------- On est souvent amené dans les algorithmes à manipuler des valeurs de vérité, nommées booléens (en anglais *boolean*, souvent abrégé par ``bool`` en informatique). Il n'existe que deux valeurs booléennes : ``True`` et ``False``. Les opérateurs sur les booléens sont les opérateurs logiques ``and``, ``or`` et ``not``\  :: >>> False and True False >>> False or True True >>> not False True L'intérêt des valeurs booléennes réside notamment dans la possibilité de les produire en comparant d'autres valeurs, puis de combiner ces résultats avec les opérateurs logiques :: >>> 1+1 == 2 # égalité True >>> 1+1 != 2 # différence False >>> 3.3 < 10/3 # inférieur strict True >>> 3.3 > 10/3 # supérieur strict False >>> 1+1 <= 2 # inférieur ou égal True >>> 1+1 >= 2 # supérieur ou égal True >>> (1+1 == 2) and (3.3 > 10/3) False .. note:: On remarque ci-dessus que le test d'égalité utilise l'opérateur ``==``, et non l'opérateur usuel ``=``. On verra ci-dessous dans la section `Variables`_ que ce dernier a un *autre* sens en Python (ainsi que dans la quasi-totalité des langages de programmation). .. index:: chaîne de caractères, str Chaînes de caractères --------------------- Python ne se limite pas aux valeurs purement mathématiques. Il peut également manipuler du texte, sous forme de *chaînes de caractères* ou tout simplement *chaînes*, (en anglais : *character string*, souvent abrégé par ``str`` en informatique), une séquence de caractères de longueur arbitraire. Python supporte le codage UNICODE, ce qui permet d'utiliser un large éventail de caractères, incluant les caractères accentués du français. Une chaîne de caractères est délimitée par les symboles ``'`` ou ``"``. Par exemple ``'hello'`` ou ``"bonjour le monde"`` sont des chaînes de caractères. .. NB: je ne rentre pas dans le détail des échappements ou des """ et '''. Les principales opérations que nous utiliserons sur les chaînes de caractères consistent à calculer leur longueur, les concaténer et en extraire des sous-chaînes :: >>> len("le monde") # longueur 8 >>> "le" + "monde" # concaténation 'lemonde' >>> "le monde"[0] # premier caractère 'l' >>> "le monde"[:3] # sous-chaîne contenant les 3 premiers caractères 'le ' >>> "le monde"[3:] # sous-chaîne commençant au 4ème caractère 'monde' Les exemples ci-dessus méritent quelques explications : * La longueur d'une chaîne prend en compte tous les caractères, y compris les espaces. * La concaténation n'insère pas d'espace ; pour obtenir le résultat ``'le monde'`` ci-dessus, il aurait fallu écrire (par exemple) ``"le" + " monde"`` (observez l'espace placé avant la lettre m). * Contrairement à d'autres langages de programmation, Python n'a pas de type caractère distinct du type chaîne ; ainsi, la troisième valeur ci-dessus est simplement une *autre* chaîne, de longueur 1. * Comme dans la plupart des langages de programmation, les chaînes de caractères sont indicées à partir de 0, donc le premier caractère a l'indice 0, le deuxième a l'indice 1, *etc*. * En Python, lorsque l'on sélectionne un sous ensemble d'une chaîne à l'aide de bornes, la borne inférieure est inclue, et la borne supérieure est exclue. Par exemple, lorsque l'on écrit ``"le monde"[3:5]``, on va sélectionner la sous-chaîne commençant à l'indice 3 et se terminant à l'indice 4, c'est-à-dire ``"mo"``. Lorsque la borne inférieur n'est pas précisée, on commence au début de la chaîne, et lorsque la borne supérieure n'est pas précisée, on va jusqu'à la fin de la chaîne. Les chaînes de caractères peuvent également être comparées avec les opérateurs de comparaison vus plus haut:: >>> "le monde" == "le " + "monde" True >>> "le monde" != "le monde " # les espaces comptent True >>> "bonjour" < "bonsoir" True >>> "bon" < "bonjour" True >>> "Z" < "a" True >>> "é" >= "z" True On voit dans les exemples ci-dessus que l'ordre induit par les opérateurs de comparaison (``<``, ``>``, ``<=`` et ``>=``) sur les chaînes de caractères n'est pas totalement intuitif. Il se rapproche de l'ordre alphabétique, mais place les lettres majuscules avant les lettres minuscules. Par ailleurs, il ne place pas correctement les lettres accentuées. Il est donc à utiliser avec précaution. Enfin, notons que les chiffres sont des caractères valides ; il ne faut cependant pas confondre les chaînes de caractères composées de chiffres avec les nombres correspondants:: >>> "123" == 123 False >>> "1" + "1" # concaténation, et non addition '11' >>> "10" < "2" # ordre alphabétique True .. sec-variables: Variables +++++++++ Maintenant que nous avons vu les types de valeurs que nos algorithmes allaient manipuler, nous allons voir comment ces valeurs sont stockées en mémoire. La notion centrale est celle de *variable*. .. glossary:: variable emplacement de la mémoire de l'ordinateur, muni d'un *nom* et contenant une valeur qui peut changer (varier) au fil du temps affectation opération consistant à fixer ou changer la valeur d'une variable L'opérateur d'affectation en Python est l'opérateur ``=`` (comme dans la majorité des langages de programmation). À gauche de l'opérateur d'affectation, on indique le nom de la variable à affecter [#affectation-multiple]_. À droite, on donne une expression dont la valeur résultante est affectée à la variable :: >>> message = "bonjour le monde" >>> message 'bonjour le monde' Après sa première affectation, une variable peut être utilisée dans une expression. Son nom est simplement remplacé par sa valeur :: >>> a = 42 >>> a+1 43 >>> a = a+1 >>> a 43 Dans l'exemple ci-dessus, la variable `a` se voir d'abord affecter la valeur 42, donc ``a+1`` vaut 43. On affecte alors l'expression ``a+1`` à la variable `a`, dont la nouvelle valeur est donc 43. .. index:: typage; langage fortement typé .. index:: typage; langage faiblement typé Langages faiblement et fortement typés -------------------------------------- On distingue deux familles de langages de programmation qui diffèrent au niveau du typage des variables. Python appartient à la famille des langages *faiblement typés*. Dans ces langages, seules les valeurs sont typées ; par exemple, 42 est de type entier, \"toto\" est de type chaîne de caractères. Les variables, en revanche, n'ont pas de type. Ainsi dans ces langages, une variable peut en théorie contenir à des moments différents des valeurs de types différents. En pratique, cependant, on évite souvent cela, car cela nuit à la lisibilité du programme. L'autre famille, celle des langage *fortement typés*, inclue des langages comme le C ou Java. Dans ces langages, toute variable est associée à un type, et ne peut contenir que des valeurs de ce type. En imposant au programmeur d'exprimer ces contraintes, ces langages sont plus rigides que leurs homologues faiblement typés, mais peuvent en contrepartie détecter plus facilement certaines erreurs. C'est notamment le cas pour les pré/post-conditions concernant le typage des paramètres, qui sont vérifiées à la compilation, et donc garanties au moment de l'exécution. Cependant, le respect des *autres* pré/post-conditions reste de la responsabilité du programmeur. .. note:: Dans les langage fortement typés, une conséquence du typage des variables est la nécessité de *déclarer* une variable avant de l'utiliser. Cette contrainte n'existe pas dans les langages faiblement typés comme Python; la première affectation fait office de déclaration. Toute utilisation d'une variable non affectée créera une erreur à l'exécution. .. rubric:: Notes de bas de page .. [#div-entière] Y compris les versions antérieures de Python. Ce n'est que depuis la version 3 que Python possède deux opérateurs distincts. .. [#affectation-multiple] On verra plus tard que, dans certains cas, il peut y avoir plusieurs noms de variables séparés par des virgules.