str et print

ATTENTION c’est peut être ici qu’on voit la différence la plus ostensible entre python2 et python3.

Création

On crée une chaine de caractère (str) en fournissant une suite de caractères entourée de guillemets:

>>> x = "abcde"
>>> x
'abcde'
>>> type(x)
<class 'str'>

Les deux types de guillemets sont utilisables:

>>> x = 'abcde'
>>> x
'abcde'
>>> type(x)
<class 'str'>

Mais on ne peut par contre pas mélanger les deux:

>>> x = "abcde'
  File "<stdin>", line 1
    x = "abcde'
              ^
SyntaxError: EOL while scanning string literal

Cela peut se révéler utile lorsque un des caractères de la séquence est lui même un guillemet

>>> phrase = "l'alphabet commence par la lettre 'a'"
>>> phrase
"l'alphabet commence par la lettre 'a'"
>>> ironie = 'ceci est une "phrase"'
>>> ironie
'ceci est une "phrase"'

Noté que l’affichage “en miroir” de l’interpréteur utilise par défaut ' sauf si c’est un caractère interne.

On peut légitimement se demander quoi faire lorsque les deux types de guillemets sont des caractères de la séquence. La syntaxe est encore la même, mais les délimiteurs sont les triples guillemets.

>>> triple = """De cette façon, j'peux "inclure" tous les caractères que je souhaite"""
>>> triple
'De cette façon, j\'peux "inclure" tous les caractères que je souhaite'

Fonction print

L’interpréteur python “reflète” automatiquement les expressions évaluées à chaque ligne. Mais dans un script si on veut un affichage il faut le demander explicitement avec la fonction print. On regardera le screencast ci-joint pour constater la différence.

Il s’avère que même dans l’interpréteur l’utilisation de print peut se révéler utile. En reprenant notre dernier exemple:

>>> triple = """De cette façon, j'peux "inclure" les caractères que je souhaite"""
>>> triple
'De cette façon, j\'peux "inclure" les caractères que je souhaite'
>>> print(triple)
De cette façon, j'peux "inclure" les caractères que je souhaite

Notez au passage le bug de colorisation dans le fichier dû à l’absence d’échappement.

Il s’avère que les objets python ont en fait deux “affichages” distincts:

La fonction print accepte n’importe quel type d’argument:

>>> x = 1
>>> type(x)
<class 'int'>
>>> print(x)
1
>>> y = (1, 2, 3)
>>> type(y)
<class 'tuple'>
>>> print(y)
(1, 2, 3)

On peut également lui passer plusieurs arguments:

>>> x = 1
>>> y = (1, 2, 3)
>>> print(x, y)
1 (1, 2, 3)
>>> print(x, "->", y)
1 -> (1, 2, 3)

Ceux-ci sont affichés les uns à la suite des autres, séparés par un espace. Cependant le séparateur est en fait contrôlable par l’argument sep:

>>> x = 1
>>> y = (1, 2, 3)
>>> print(x, y, x, y)
1 (1, 2, 3) 1 (1, 2, 3)
>>> print(x, y, x, y, sep=" -> ")
1 -> (1, 2, 3) -> 1 -> (1, 2, 3)

On peut également contrôlé ce qui est inséré en fin d’affichage via l’argument end. Par défaut on passe à la ligne:

>>> print("blabla")
blabla
>>> print("blabla", end=" * ")
blabla * >>>

Caractères échappés

Le dernier exemple de la partie Création, montre qu’un caractère a en fait un rôle spécial. Il s’agit du backslash \.

On dit qu’il sert à échapper certains caractères pour leur enlever/donner un sens spécial. Ainsi on enlève le rôle de délimiteur d’un guillemet:

>>> essai = 'je peux inclure un \' interne comme ça'
>>> essai
"je peux inclure un ' interne comme ça"

Ou on donne un sens particulier aux lettres.

>>> newline = "Première ligne.\nDeuxième ligne."
>>> print(newline)
Première ligne.
Deuxième ligne.
>>> print(repr(newline))
'Première ligne.\nDeuxième ligne.'

On voit au passage bien ici l’intérêt que peut avoir repr.

Le \n se lit newline, il sert à inclure un saut de ligne. Notons que l’on peut aussi le triple guillemet pour inclure “naturellement” des sauts de ligne.

>>> texte = """Première ligne
... Deuxième ligne.
... Troisième ligne.
... """
>>> print(texte)
Première ligne
Deuxième ligne.
Troisième ligne.

>>> texte
'Première ligne\nDeuxième ligne.\nTroisième ligne.\n'

Il y a de nombreux caractères échappés (voir la section aller plus loin pour une référence).

On notera que pour avoir explicitement le backslash il doit être échappé!

>>> exemple = "blabla\\blabla"
>>> print(exemple)
blabla\blabla
>>> print(repr(exemple))
'blabla\\blabla'

Une utilisation particulière de l’échappement est l’inclusion de caractère unicode n’existant pas sur le clavier:

>>> print("\uFDFD")
﷽
>>> print("\U0000FDFD")
﷽
>>> print("\N{Arabic Ligature Bismillah Ar-Rahman Ar-Raheem}")
﷽

La première version permet d’utiliser le code UTF-16, la seconde UTF-32 la troisième le nom standard du caractère. De nombreux caractères sont disponibles ainsi

>>> print("\u2A0C")
⨌
>>> print("\U0001F604")
😄

On peut aller voir pour une liste.

Pour conclure cette partie, indiquons juste qu’il y a une syntaxe spéciale de création de str\ perd son rôle. On utilise la préfixe r (pour raw):

>>> exemple = r"blabla\blabla"
>>> print(exemple)
blabla\blabla
>>> print(repr(exemple))
'blabla\\blabla'

Insertion de variables

Finissons cette partie par la description d’un mécanisme permettant d’insérer des variables dynamiquement dans une chaine de caractères. On utilise pour cela des “f-strings”.

On utilisera des accolades pour signaler que ce qui est à l’intérieur est le nom de la variable à insérer.

>>> x = 1
>>> y = 2
>>> ma_chaine = f"x vaut {x}, y vaut {y}"
>>> print(ma_chaine)
x vaut 1, y vaut 2

Le mécanisme n’existe qu’à partir de python 3.6, d’autres façons de procéder existaient avant (et encore) mais on se concentrera sur celui là.

On peut en fait rentrer une expression entre les accolades, python va alors l’évaluer.

>>> x = 2
>>> y = 3
>>> addition = f"{x} + {y} = {x+y}"
>>> print(addition)
2 + 3 = 5

Notez bien que le préfixe f est crucial ici:

>>> x = 2
>>> y = 3
>>> addition = "{x} + {y} = {x+y}"
>>> print(addition)
{x} + {y} = {x+y}

Exercices

  1. Exécuter le code suivant:

    >>> un = "Premier"
    >>> deux = "Deuxième"
    >>> tout = un + deux
    >>> print(tout)

    Que se passe-t-il quand on ajoute deux str?

  2. Exécuter le code suivant:

    >>> ligne = "-*" * 30
    >>> print(ligne)

    Que produit la multiplication d’une str et d’un int?

  3. Trouvez un moyen économe de construire la chaine bizarre pour qu’on ait

    >>> print(bizarre)
    <-*->
    <-*-><-*->
    <-*-><-*-><-*->
  4. Comment pouvez vous produire facilement la table de multiplication par 9?

  5. Exécutez le code

    >>> face = "\u0028\u0020\u0361\u00b0\u0020\u035c\u0296\u0020\u0361\u00b0\u0029"
    >>> print(face)

    En déduire le code pour l’affichage de ( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°).

Pour aller plus loin

On pourra consulter

>>> help("STRINGS")

pour la description complète de la syntaxe des chaines de caractères.

Finalement

>>> help("UNICODE")

permettra d’obtenir une description des caractères utilisables.

Corrections

  1. On a l’affichage suivant:

    >>> un = "Premier"
    >>> deux = "Deuxième"
    >>> tout = un + deux
    >>> print(tout)
    PremierDeuxième

    On voit que l’addition de deux str effectue la concaténation on met bout à bout les deux séquences pour en créer une nouvelle.

  2. On a l’affichage suivant:

    >>> ligne = "-*" * 30
    >>> print(ligne)
    -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

    On voit que la multiplication sert à répéter la séquence de caractères un certain nombre de fois.

  3. On pose une variable intermédiaire et on utilise l’addition et la multiplication:

    >>> symbole = "<-*->"
    >>> bizarre = symbole * 1 + "\n" + symbole * 2 + "\n" + symbole * 3
  4. Pour l’instant on peut produire le code ci-dessous, mais on commence déjà à voir le besoin de boucle.

    >>> x = 1
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 1 = 9
    ------------
    >>> x = 2
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 2 = 18
    ------------
    >>> x = 3
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 3 = 27
    ------------
    >>> x = 4
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 4 = 36
    ------------
    >>> x = 5
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 5 = 45
    ------------
    >>> x = 6
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 6 = 54
    ------------
    >>> x = 7
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 7 = 63
    ------------
    >>> x = 8
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 8 = 72
    ------------
    >>> x = 9
    >>> print("-" * 12 + "\n" + f"9 x {x} = {9 * x}" + "\n" + "-" * 12)
    ------------
    9 x 9 = 81
    ------------
  5. On a

    bis = "\u0028\u0020\u0361\u00b0\u0028\u0020\u0361\u00b0\u0020\u035c\u0296\u0028\u0020\u0361\u00b0\u0020\u035c\u0296\u0020\u0361\u00b0\u0029\u0296\u0020\u0361\u00b0\u0029\u0020\u0361\u00b0\u0029"
    >>> print(bis)
    ( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°)

    Si on n’avait pas envie de réfléchir au puzzle on pouvait utiliser le code suivant (qui on l’admet anticipe sur des prochaines séances)

    >>> face = "( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°)"
    >>> codes = tuple(f"{ord(car):04x}" for car in face)
    >>> codes
    ('0028', '0020', '0361', '00b0', '0028', '0020', '0361', '00b0', '0020', '035c', '0296', '0028', '0020', '0361', '00b0', '0020', '035c', '0296', '0020', '0361', '00b0', '0029', '0296', '0020', '0361', '00b0', '0029', '0020', '0361', '00b0', '0029')
    >>> resultat = r"\u" + r"\u".join(codes)
    >>> print(resultat)
    \u0028\u0020\u0361\u00b0\u0028\u0020\u0361\u00b0\u0020\u035c\u0296\u0028\u0020\u0361\u00b0\u0020\u035c\u0296\u0020\u0361\u00b0\u0029\u0296\u0020\u0361\u00b0\u0029\u0020\u0361\u00b0\u0029