4. Die Zeichenfolgen

4.1. Skript [str_01]: Notation von Zeichenfolgen
Das Skript [str_01] lautet wie folgt:
# Zeichenfolgen
# drei mögliche Darstellungsformen
chaine1 = "un"
chaine2 = 'deux'
chaine3 = """hélène va au
marché acheter des légumes"""
# Anzeige
print(f"chaine1=[{chaine1}], chaine2=[{chaine2}], chaine3=[{chaine3}]")
Anmerkungen
- Zeile 3: eine durch Anführungszeichen " begrenzte Zeichenkette;
- Zeile 4: eine durch Apostrophe ' begrenzte Zeichenkette;
- Zeile 5: eine durch dreifache Anführungszeichen """ begrenzte Zeichenkette. In diesem Fall kann sich die Zeichenkette über mehrere Zeilen erstrecken;
Die Ergebnisse lauten wie folgt:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_01.py
chaine1=[un], chaine2=[deux], chaine3=[hélène va au
marché acheter des légumes]
Process finished with exit code 0
4.2. Skript [str_02]: Die Methoden der Klasse <str>
Das Skript [str_02] stellt einige der Methoden der Klasse <str> vor, bei der es sich um die Klasse für Zeichenketten handelt:
# Funktionen für Zeichenfolgen
# Zeichenkette in Kleinbuchstaben
print(f"'ABCD'.lower()={'ABCD'.lower()}")
# Zeichenkette in Großbuchstaben
print(f"'abcd'.upper()={'abcd'.upper()}")
# Zeichen Nr. 2
print(f"'cheval[2]={'cheval'[2]}")
# Teilzeichenfolge mit den Zeichen 5 und 6
print(f"'caractères accentués'[5:7]={'caractères accentués'[5:7]}")
# Teilzeichenfolge ab Zeichen 4 einschließlich
print(f"'caractères accentués'[4:]={'caractères accentués'[4:]}")
# Teilzeichenfolge bis zum Zeichen 6 (ausschließlich)
print(f"'caractères accentués'[:5]={'caractères accentués'[:5]}")
# Länge der Zeichenfolge
print(f"len('123')={len('123')}")
# Entfernung der Leerzeichen vor und nach der Zeichenfolge
print(f"' abcd '.strip()=[{' abcd '.strip()}]")
# Entfernung der Leerzeichen nach der Zeichenfolge
print(f"' abcd '.rstrip()=[{' abcd '.rstrip()}]")
# Entfernung der Leerzeichen vor der Zeichenfolge
print(f"' abcd '.lstrip()=[{' abcd '.lstrip()}]")
# Der Begriff „Leerzeichen“ umfasst tatsächlich verschiedene Zeichen
str = ' \r\nabcd \t\f'
print(f"str.strip()=[{str.strip()}]")
# Ersetzen einer Teilzeichenfolge durch eine andere
print(f"'abcd'.replace('a','x')={'abcd'.replace('a', 'x')}")
print(f"'abcd'.replace('ab','xy')={'abcd'.replace('ab', 'xy')}")
# Suche nach einer Teilzeichenfolge: Gibt die Position zurück oder -1, wenn die Teilzeichenfolge nicht gefunden wurde
print(f"'abcd'.find('bc')={'abcd'.find('bc')}")
print(f"'abcd'.find('bc')={'abcd'.find('Bc')}")
# Anfang einer Zeichenkette
print(f"'abcd'.startswith('ab')={'abcd'.startswith('ab')}")
print(f"'abcd'.startswith('x')={'abcd'.startswith('x')}")
# Ende einer Zeichenkette
print(f"'abcd'.endswith('cd')={'abcd'.endswith('cd')}")
print(f"'abcd'.endswith('x')={'abcd'.endswith('x')}")
# Umwandlung einer Liste von Zeichenfolgen in eine Zeichenfolge
print(f"'[X]'.join(['abcd', '123', 'èéà'])={'[X]'.join(['abcd', '123', 'èéà'])}")
print(f"''.join(['abcd', '123', 'èéà'])={''.join(['abcd', '123', 'èéà'])}")
# Wechsel von einer Zeichenkette zu einer Liste von Zeichenketten
print(f"'abcd 123 cdXY'.split('cd')={'abcd 123 cdXY'.split('cd')}")
# Wörter aus einer Zeichenkette extrahieren
print(f"'abcd 123 cdXY'.split(None)={'abcd 123 cdXY'.split(None)}")
Die Kommentare in Verbindung mit den erzielten Ergebnissen reichen aus, um das Skript zu verstehen. Die Ergebnisse lauten wie folgt:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_02.py
'ABCD'.lower()=abcd
'abcd'.upper()=ABCD
'Pferd[2]=e
'Zeichen mit Akzenten'[5:7]=tè
'Zeichen mit Akzenten'[4:]=Zeichen mit Akzenten
'Zeichen mit Akzenten'[:5]=Zeichen
len('123')=3
' abcd '.strip()=[abcd]
' abcd '.rstrip()=[ abcd]
' abcd '.lstrip()=[abcd ]
str.strip()=[abcd]
'abcd'.replace('a','x')=xbcd
'abcd'.replace('ab','xy')=xycd
'abcd'.find('bc')=1
'abcd'.find('bc')=-1
'abcd'.startswith('ab')=True
'abcd'.startswith('x')=False
'abcd'.endswith('cd')=True
'abcd'.endswith('x')=False
'[X]'.join(['abcd', '123', 'èéà'])=abcdQZXW2HTMLBW1hdZQX123QZXW2HTMLBW1hdZQXèéà
''.join(['abcd', '123', 'èéà'])=abcd123èéà
'abcd 123 cdXY'.split('cd')=['ab', ' 123 ', 'XY']
'abcd 123 cdXY'.split(None)=['abcd', '123', 'cdXY']
Process finished with exit code 0
4.3. Skript [str_03]: Kodierung von Zeichenketten (1)
Das Skript [str_03] vermittelt Grundlagen zur Kodierung von Zeichenfolgen:
# Zeichenkodierung
# Zeichenkette vom Typ „str“
str = "hélène va au marché acheter des légumes"
print(f"str=[{str}, type={type(str)}]")
# UTF-8-Kodierung
print("--- utf-8")
bytes1 = str.encode('utf-8')
print(f"bytes1={bytes1}, type={type(bytes1)}")
bytes2 = bytes(str, 'utf-8')
print(f"bytes2={bytes2}, type={type(bytes2)}")
# Kodierung iso-8859-1
print("--- iso-8859-1")
bytes1 = str.encode('iso-8859-1')
print(f"bytes1={bytes1}, type={type(bytes1)}")
bytes2 = bytes(str, 'iso-8859-1')
print(f"bytes2={bytes2}, type={type(bytes2)}")
# Kodierung latin1=iso-8859-1
print("--- latin1")
bytes1 = str.encode('latin1')
print(f"bytes1={bytes1}, type={type(bytes1)}")
bytes2 = bytes(str, 'latin1')
print(f"bytes2={bytes2}, type={type(bytes2)}")
Die Kodierung einer Zeichenkette vom Typ <str> erzeugt eine Binärzeichenkette, in der jedes Zeichen der Zeichenkette durch ein oder mehrere Bytes dargestellt wird. Es gibt verschiedene Arten der Kodierung. Das obige Skript stellt die beiden im westlichen Raum gängigsten vor: „utf-8“ und „iso-8859-1“, auch „latin1“ genannt.
Das Prinzip der Kodierung/Dekodierung wird im Folgenden veranschaulicht (Quelle: |https://realpython.com/python-encodings-guide/ |):

Anmerkungen
- Zeilen 4–5: Die ursprüngliche Zeichenkette, die kodiert werden soll. Instanzen des Typs <str> sind Unicode-Zeichenfolgen |https://docs.python.org/3/howto/unicode.html|, |https://realpython.com/python-encodings-guide/ |;
- Zeilen 6–11: Zwei Möglichkeiten, eine Zeichenkette in UTF68 zu kodieren:
- Zeile 8: str.encode('utf-8);
- Zeile 10: bytes(str, 'utf-8');
- Zeilen 12–17: Das Gleiche wird mit der Kodierung „iso-8859-1“ wiederholt;
- Zeilen 18–23: „latin1“ ist eine andere Bezeichnung für die Kodierung „iso-8859-1“;
Die Ergebnisse lauten wie folgt:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_03.py
str=[hélène va au marché acheter des légumes, type=<class 'str'>
--- utf-8
bytes1=b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes', type=<class 'bytes'>
bytes2=b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes', type=<class 'bytes'>
--- iso-8859-1
bytes1=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>
bytes2=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>
--- latin1
bytes1=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>
bytes2=b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes', type=<class 'bytes'>
Process finished with exit code 0
Kommentare
- Zeile 4: Man sieht, dass die Zeichen mit Akzenten auf zwei Bytes kodiert wurden:
- é: [\xc3\xa9], was der Binärfolge 11000011 10101001 entspricht;
- è: [\xc3\xa8], was der Binärfolge 11000011 10101000 entspricht;
- Zeile 7: Bei der Kodierung nach ISO-8859-1 werden diese beiden Zeichen mit Akzent unterschiedlich kodiert:
- é: [\xe9], was der Binärfolge 11101001 entspricht;
- è: [\xe8], was der Binärfolge 11101000 entspricht;
4.4. Skript [str_04]: Kodierung von Zeichenfolgen (2)
Das Skript [str_04] stellt zwei weitere Kodierungsarten vor: „base64“ und „quoted-printable“. Diese beiden Kodierungen kodieren keine Unicode-Zeichenfolgen, sondern Binärdaten. Wenn man beispielsweise ein Word-Dokument an eine E-Mail anhängt, wird dieses je nach verwendetem E-Mail-Programm einer der beiden Kodierungen unterzogen. Dies gilt für die meisten angehängten Dateien.
Das Skript lautet wie folgt:
# Kodierung/Dekodierung
import codecs
# Zeichenkette
print("---- chaîne unicode")
str1 = "hélène va au marché acheter des légumes"
print(f"str1=[{str1}], type(str1)={type(str1)}")
# Kodierung utf-8
print("---- chaîne unicode -> binaire utf-8")
bytes1 = bytes(str1, "utf-8")
print(f"bytes1=[{bytes1}], type(bytes1)={type(bytes1)}")
# UTF-8-Dekodierung
print("---- binaire utf-8 -> chaîne unicode")
str2 = bytes1.decode("utf-8")
print(f"str2=[{str2}], type(str2)={type(str2)}")
print(f"str2==str1={str2 == str1}")
# Kodierung ISO-8859-1
print("---- chaîne unicode -> binaire iso-8859-1")
bytes2 = bytes(str1, "iso-8859-1")
print(f"bytes2=[{bytes2}], type(bytes2)={type(bytes2)}")
# Dekodierung ISO-8859-1
print("---- binaire iso-8859-1 -> chaîne unicode")
str3 = bytes2.decode("iso-8859-1")
print(f"str3=[{str3}], type(str3)={type(str3)}")
print(f"str3==str1={str3 == str1}")
# Dekodierungsfehler – bytes1 ist in UTF-8 – wird in ISO-8859-1 dekodiert
print("--- binaire utf-8 (décodage iso-8859-1) --> chaîne unicode")
str4 = bytes1.decode("iso-8859-1")
print(f"str4=[{str4}], type(str4)={type(str4)}")
# UTF-8-Kodierung einer Unicode-Zeichenkette
print("---- chaîne unicode -> binaire utf-8")
bytes3 = codecs.encode(str1, "utf-8")
print(f"bytes3=[{bytes3}], type(bytes3)={type(bytes3)}")
# Base64-Kodierung einer binären Zeichenkette UTF-8
print("---- binaire utf-8 -> binaire base64")
bytes4 = codecs.encode(bytes1, "base64")
print(f"bytes4=[{bytes4}], type(bytes4)={type(bytes4)}")
# Rückwandlung in die ursprüngliche Unicode-Zeichenkette
print("---- binaire base64 -> binaire utf-8 -> chaîne unicode")
str6 = codecs.decode(bytes4, "base64").decode("utf-8")
print(f"str6=[{str6}], type(str6)={type(str6)}")
# Kodierung einer Binärzeichenfolge in „quoted-printable“
print("---- binaire utf-8 -> binaire quoted-printable")
str7 = codecs.encode(bytes1, "quoted-printable")
print(f"str7=[{str7}], type(str7)={type(str7)}")
# Rückwandlung in die ursprüngliche Unicode-Zeichenkette
print("---- binaire quoted-printable -> binaire utf-8 -> chaîne unicode")
str8 = codecs.decode(str7, "quoted-printable").decode("utf-8")
print(f"str8=[{str8}], type(str8)={type(str8)}")
Kommentare
- Zeile 2: Das Modul [codecs] ermöglicht die Kodierungen „base64“ und „quoted-printable“. Es kann noch viele weitere Kodierungen durchführen;
- Zeilen 4–7: Die Unicode-Zeichenkette, die verschiedenen Kodierungen unterzogen wird;
- Zeilen 9–12: UTF-8-Kodierung. Das Ergebnis ist eine Binärdatei;
- Zeilen 14–18: UTF-8-Dekodierung, um zur ursprünglichen Unicode-Zeichenkette zurückzukehren;
- Zeilen 20–29: Der gleiche Vorgang wird mit der Kodierung „iso-8859-1“ wiederholt;
- Zeilen 31–34: Es wird ein Dekodierungsfehler gezeigt:
- Zeile 33:
bytes1ist eine in „UTF-8“ kodierte Binärzeichenfolge. Sie wird in „iso-8859-1“ dekodiert; - Zeilen 36–39: Eine weitere Möglichkeit, eine Zeichenkette mit dem Modul [codecs] in UTF-8 zu kodieren;
- Zeilen 41–44: Eine binäre „UTF-8“-Zeichenkette wird in „Base64“ kodiert;
- Zeilen 46–49: zeigen, wie man von der binären „Base64“-Zeichenkette zur ursprünglichen Unicode-Zeichenkette gelangt;
- Zeilen 51–59: Dieser Vorgang wird mit einer „quoted-printable“-Kodierung anstelle von „base64“ wiederholt;
Die Ergebnisse lauten wie folgt:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/strings/str_04.py
---- chaîne unicode
str1=[hélène va au marché acheter des légumes], type(str1)=<class 'str'>
---- chaîne unicode -> binaire utf-8
bytes1=[b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes'], type(bytes1)=<class 'bytes'>
---- binaire utf-8 -> chaîne unicode
str2=[hélène va au marché acheter des légumes], type(str2)=<class 'str'>
str2==str1=True
---- chaîne unicode -> binaire iso-8859-1
bytes2=[b'h\xe9l\xe8ne va au march\xe9 acheter des l\xe9gumes'], type(bytes2)=<class 'bytes'>
---- binaire iso-8859-1 -> chaîne unicode
str3=[hélène va au marché acheter des légumes], type(str3)=<class 'str'>
str3==str1=True
--- binaire utf-8 (décodage iso-8859-1) --> chaîne unicode
str4=[hélène va au marché acheter des légumes], type(str4)=<class 'str'>
---- chaîne unicode -> binaire utf-8
bytes3=[b'h\xc3\xa9l\xc3\xa8ne va au march\xc3\xa9 acheter des l\xc3\xa9gumes'], type(bytes3)=<class 'bytes'>
---- binaire utf-8 -> binaire base64
bytes4=[b'aMOpbMOobmUgdmEgYXUgbWFyY2jDqSBhY2hldGVyIGRlcyBsw6lndW1lcw==\n'], type(bytes4)=<class 'bytes'>
---- binaire base64 -> binaire utf-8 -> chaîne unicode
str6=[hélène va au marché acheter des légumes], type(str6)=<class 'str'>
---- binaire utf-8 -> binaire quoted-printable
str7=[b'h=C3=A9l=C3=A8ne=20va=20au=20march=C3=A9=20acheter=20des=20l=C3=A9gumes'], type(str7)=<class 'bytes'>
---- binaire quoted-printable -> binaire utf-8 -> chaîne unicode
str8=[hélène va au marché acheter des légumes], type(str8)=<class 'str'>
Process finished with exit code 0
- Zeilen 14–15: Eine UTF-8-Binärzeichenfolge wird mit dem falschen Decoder „iso-8859-1“ in eine Unicode-Zeichenkette dekodiert. Daher sind einige der erzeugten Unicode-Zeichen fehlerhaft, in diesem Fall die Zeichen mit Akzenten;
- Zeilen 18–19: Bei der „base64“-Kodierung werden 64 Zeichen ASCII (7-Bit-kodiert) verwendet, um eine beliebige Binärdatei zu kodieren. Dies erhöht, wie man sieht, die Größe der Binärdatei der Zeichenkette;
- Zeilen 22–23: Auch die „quoted-printable“-Kodierung besteht darin, die Zeichen ASCII (7-Bit-kodiert) zur Kodierung einer beliebigen Binärdatei zu verwenden;
Man beachte, dass man, wenn man eine Binärdatei – beispielsweise aus dem Internet – erhält, die einen Text darstellt, die verwendeten Kodierungen kennen muss, um diesen Text wiederherzustellen.