Licence CC BY-NC-ND, Thierry Parmentelat & Arnaud Legout
from IPython.display import HTML
HTML(filename="_static/style.html")
séquences & chaines#
c’est quoi une séquence ?#
suite finie et ordonnée d’objets
du coup indexable, on peut écrire
S[n]en Python, les indices commencent à 0
peuvent contenir des duplications
les séquences dans le langage Python (entre autres):
mutable
list,bytearray
immutable
str,bytes,tuple,range
les chaines (str) sont des séquences
nous allons voir pour commencer des choses valables sur toutes les séquences, et donc en particulier sur les chaines de caractères, puisque les chaines sont des séquences
fonctions sur toutes les séquences#
indexation, longueur#
S[i]retourne l’élément d’indice i
len(S)donne la taille en nombre d’éléments
les séquences sont des itérables#
un itérable en Python, c’est un objet sur lequel on peut faire un for
for item in S:
# do something with item
concaténation, comparaisons#
S + Tretourne une nouvelle séquence qui est la concaténation de S et T
S*noun*Sretourne une nouvelle séquence qui est la concaténation de n shallow copies de S
sum(S)(resp.min(S)etmax(S))retourne la somme des éléments de S (resp. le plus petit, le plus grand)
en fait sur tous les itérables
en fait les fonctions
sum,minetmaxs’appliquent à n’importe quel itérable
toutes les séquences sont des itérables, mais tous les itérables ne sont pas des séquences
la famille des itérables est donc plus large que les séquences
appartenance, recherches#
x in S; selon les types:Truesi un élément de S est égal à x
(e.g. S est unelist)Truesi S contient x
(e.g. S est unestr)
diverses méthodes (voir docs):
S.count(a)retourne le nombre d’occurrences de a dans S
S.index(a),S.find(a)
retourne l’indice de la première occurrence de a dans S
slicing#
S[i:j]retourneune nouvelle séquence de même type
contenant tous les éléments de l’indice i à l’indice j-1
S[i:j:k]retourneune nouvelle séquence de même type
prenant tous les éléments de l’indice i à l’indice j-1,
par sauts de k éléments
les indices
i,jetkpeuvent être négatifs
voyons des exemples de tout ceci
slicing et numpy
la notion de slicing est très massivement utilisée dans toutes les librairies numériques, notamment en numpy
indices omis et négatifs#
omettre les bornes
compter depuis la fin, avec un indice négatif
s = "egg, bacon"
s[0:3]
'egg'
# si on omet une borne
# ce sera le début ..
s[:3]
'egg'
# ... ou la fin:
s[5:]
'bacon'
# les indices peuvent être négatifs
s[-3:10]
'con'
# tout entier: une shallow-copy
s[:]
'egg, bacon'
les bornes#
La convention est choisie pour pouvoir facilement “encastrer” les slices:
s[0:3]
'egg'
s[3:6]
', b'
s[6:]
'acon'
s[0:3] + s[3:6] + s[6:] == s
True
le pas#
on peut préciser un pas
qui peut aussi être négatif
ou omis (défaut 1)
s[0:10:2]
'eg ao'
s[::2]
'eg ao'
s[:8:3]
'e,a'
s[-2::-3]
'obg'
pas d’exception#
les slices ont un comportement plus permissif que l’indexation
# Si j'essaie d'utiliser un index inexistant
try: s[100]
except Exception as e: print("OOPS", e)
OOPS string index out of range
# par contre avec un slice, pas de souci
s[5:100]
'bacon'
# vraiment..
s[100:200]
''
exemples#
s[-1]
'n'
s[-3:-1]
'co'
s[:-3]
'egg, ba'
s[::-1]
'nocab ,gge'
s[2:0:-1]
'gg'
s[2::-1]
'gge'
formes idiomatiques#
s = [1, 2, 3]
# une copie simple
s[:]
'egg, bacon'
# copie renversée
s[::-1]
'nocab ,gge'
str pour manipuler du texte#
le type
strest un cas particuliers de séquencequi permet de manipuler du texte
un caractère ce n’est pas un octet
avec l’encodage le plus répandu aujourd’hui (UTF-8), les caractères ASCII tiennent sur un octet
mais ce sont les seuls: un é par exemple occupe 2 octets; un ‰ occupe 3 octets; un 🚀 occupe 4 octets
si vous avez besoin de manipuler des données brutes - typiquement si vous lisez un fichier binaire - il vous faut utiliser le type bytes que nous verrons plus tard
écrire une str de manière littérale#
une chaîne de caractères est définie de manière équivalente par des simples ou doubles guillemets (
'ou")on peut ainsi facilement inclure un guillemet
# une chaine entre double quotes
# pas de souci pour les accents
print("c'est l'été")
c'est l'été
# entre simple quotes
print('on se dit "pourquoi pas"')
on se dit "pourquoi pas"
sur plusieurs lignes#
pour écrire une chaîne sur plusieurs lignes on utilise
"""ou'''
# bien sûr ici vous pouvez remplacer les """ par '''
print("""et pour entrer plusieurs lignes,
ou bien des chaines avec des " et des '
c'est facile aussi""")
et pour entrer plusieurs lignes,
ou bien des chaines avec des " et des '
c'est facile aussi
chaînes de caractères accolées#
lorsque vous voulez entrer une chaine un peu longue
vous pouvez simplement accoler deux chaines dans votre source:
s = "le début" " et la fin"
print(s)
le début et la fin
s = ("une chaine trop longue"
" pour tenir sur une ligne")
print(s)
une chaine trop longue pour tenir sur une ligne
les parenthèses sont importantes
notez bien les parenthèses dans ce deuxième exemple, car sinon c’est une erreur de syntaxe
échappements dans les chaines#
le caractère
\a un sens particulier dans les chaines écrites de manière littérale dans le programmeon écrit un retour chariot avec un
\nune tabulation avec
\tles guillemets peuvent être échappés (e.g. pour entrer un
'dans une chaine délimitée avec un')un backslash avec
\\enfin on peut aussi entrer des caractères exotiques par leur codepoint avec
\x\u\U
s = "deux\nlignes"
print(s)
deux
lignes
s = 'des\ttrucs\tespacés'
print(s)
des trucs espacés
# imaginons qu'on ait les deux sortes de guillemets
s = "simple' double\""
print(s)
simple' double"
s = 'backslash \\\tquote \''
print(s)
backslash \ quote '
raw-strings#
voici un problème commun, surtout sous Windows:
s = 'C:\Temp\test.txt'
print(s)
C:\Temp est.txt
<>:1: SyntaxWarning: invalid escape sequence '\T'
<>:1: SyntaxWarning: invalid escape sequence '\T'
/tmp/ipykernel_658/895050390.py:1: SyntaxWarning: invalid escape sequence '\T'
s = 'C:\Temp\test.txt'
\Tn’existe pas comme échappement; Python interprète correctement\Tmais
\test compris comme une tabulation !!
Python-3.12
il semble même qu’en 3.12, un \T dans une chaine provoque carrément une erreur de syntaxe - ce qui est sans doute mieux au sens où au moins on détecte l’erreur plus tôt…
pour résoudre ce problème, on peut utiliser des double-backslash \\, mais ce n’est vraiment pas élégant
la bonne solution consiste à utiliser une “raw string”, dans laquelle les backslash ne sont pas interprétés
# pour créer une raw-string, simplement faire précéder le string d'un 'r'
s = r'C:\Temp\test1.bin'
print(s)
C:\Temp\test1.bin
préférez le / pour les chemins de fichier
notez que le plus souvent, vous pouvez aussi bien utiliser un / au lieu d’un \ dans les chemins de fichiers sous Windows, ce qui résoud tous les problèmes d’échappement
les raw-strings restent une feature bien pratique dans d’autres contextes, notamment avec les expressions régulières, que nous n’avons pas pu utiliser comme exemple ici puisqu’on n’en a pas encore parlé..
docstrings#
une docstring est une chaine littérale insérée au tout début du code d’une fonction (ou classe ou module) et qui sert à la documenter
on utilise souvent les triples guillemets pour cela
def double(n):
"""
Returns the double of its input parameter
The help message usually spans several lines
"""
return 2*n
help(double)
Help on function double in module __main__:
double(n)
Returns the double of its input parameter
The help message usually spans several lines
opérations sur les str#
toutes les opérations des séquences#
que l’on a déjà vues :
s1 = 'abcdéfg'
s2 = 'bob'
len(s1)
7
# concaténation
s1 + s2
'abcdefbob'
'abcdefbob'
# slicing
s1[-1::-2]
'géca'
'=' * 30
'=============================='
# est-ce une sous-chaine ?
'cdé' in s1
True
# à quelle position ?
s1.index('cdé')
2
objet str non mutable#
par contre ATTENTION un str n’est pas mutable
try:
s1[2] = 'x'
except TypeError as e:
print("OOPS", e, type(e))
OOPS 'str' object does not support item assignment <class 'TypeError'>
méthodes sur les str#
strip()#
# j'ai lu une chaine dans un fichier
# je ne sais pas trop s'il y a des espaces à la fin
# et si la chaine contient un newline
dirty = " des blancs au début et à la fin et un newline \n"
dirty
' des blancs au début et à la fin et un newline \n'
# c'est la méthode la plus simple pour nettoyer
dirty.strip()
'des blancs au début et à la fin et un newline'
utilisez rstrip() pour nettoyer les lignes lues dans un fichier
lorsqu’on nettoie une ligne qu’on a lue dans un fichier, on peut envisager
d’utiliser rstrip() qui ne nettoie qu’à droite, là où se situe le NEWLINE
split() et join()#
# une chaine à découper
s = "une phrase\nsur deux lignes"
s
'une phrase\nsur deux lignes'
# sans argument, split
# découpe selon les espaces
# et tabulations et newline
liste = s.split()
liste
['une', 'phrase', 'sur', 'deux', 'lignes']
# recoller les morceaux
"".join(liste)
'unephrasesurdeuxlignes'
# le plus souvent
" ".join(liste)
'une phrase sur deux lignes'
# ou n'importe quel autre séparateur
"+++".join(liste)
'une+++phrase+++sur+++deux+++lignes'
remplacements, recherches#
s = "une petite phrase"
s.replace('petite', 'grande')
'une grande phrase'
# l'index du premier caractère
s.find('hra')
12
s[12]
'h'
et plein d’autres..#
de nombreuses méthodes disponibles
personne ne retient l’intégralité des méthodes sur les types de base
le bon réflexe : chercher dans la dos Python qui est très bien faite
google les simples mots clés ‘python str’, vous trouvez
un peu d’introspection (avancé)#
disons qu’on voudrait savoir combien de méthodes sont disponibles sur les chaines.
type("abc")
str
str
str
# 'str' est une variable prédéfinie, qui référence
# le type (la classe) de toutes les chaines
type("abc") is str
True
# du coup son type, c'est .. le type <type>
type(str)
type
un peu d’introspection…#
# peu importe... quoi qu'il en soit, dir(str) retourne la liste
# des noms de méthodes connues sur cette classe;
# regardons par exemple les premiers et les derniers
dir(str)[:2], dir(str)[-2:]
(['__add__', '__class__'], ['upper', 'zfill'])
# avec len() je peux savoir combien il y en a
len(dir(str))
81
# mais en fait, pour un décompte significatif
# on enlève celles dont le nom contient `__`
methods = [method for method in dir(str)
if '__' not in method]
len(methods)
47
# est-ce que les chaines ont une méthode 'split' ?
'split' in methods
True