Skip to content

4. Символьні рядки

Image

4.1. Скрипт [str_01]: запис символьних рядків

Скрипт [str_01] має такий вигляд:


# рядки символів
# три можливі формати
chaine1 = "un"
chaine2 = 'deux'
chaine3 = """hélène va au
 marché acheter des légumes"""
# відображення
print(f"chaine1=[{chaine1}], chaine2=[{chaine2}], chaine3=[{chaine3}]")

Коментарі

  • рядок 3: рядок, обмежений лапками ";
  • рядок 4: рядок, обмежений апострофами ';
  • рядок 5: рядок, обмежений потрійними лапками """. У цьому випадку рядок може займати кілька рядків;

Результати такі:


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. Скрипт [str_02]: методи класу <str>

Скрипт [str_02] демонструє деякі методи класу <str>, який є класом символьних рядків:


# функції над символьними рядками
# рядок малими літерами
print(f"'ABCD'.lower()={'ABCD'.lower()}")
# рядок у верхньому регістрі
print(f"'abcd'.upper()={'abcd'.upper()}")
# символ № 2
print(f"'cheval[2]={'cheval'[2]}")
# підрядок із символами 5 і 6
print(f"'caractères accentués'[5:7]={'caractères accentués'[5:7]}")
# підрядок, починаючи з 4-го символу включно
print(f"'caractères accentués'[4:]={'caractères accentués'[4:]}")
# підрядок до символу 6 (не включно)
print(f"'caractères accentués'[:5]={'caractères accentués'[:5]}")
# довжина рядка
print(f"len('123')={len('123')}")
# видалення пробілів перед і після рядка
print(f"'  abcd '.strip()=[{'  abcd '.strip()}]")
# видалення пробілів, що йдуть після ланцюжка
print(f"'  abcd '.rstrip()=[{'  abcd '.rstrip()}]")
# видалення пробілів, що передують рядку
print(f"'  abcd '.lstrip()=[{'  abcd '.lstrip()}]")
# термін «пробіл» насправді охоплює різні символи
str = '  \r\nabcd \t\f'
print(f"str.strip()=[{str.strip()}]")
# заміна одного підрядка на інший
print(f"'abcd'.replace('a','x')={'abcd'.replace('a', 'x')}")
print(f"'abcd'.replace('ab','xy')={'abcd'.replace('ab', 'xy')}")
# пошук підрядка: повертає позицію або -1, якщо підрядок не знайдено
print(f"'abcd'.find('bc')={'abcd'.find('bc')}")
print(f"'abcd'.find('bc')={'abcd'.find('Bc')}")
# початок рядка
print(f"'abcd'.startswith('ab')={'abcd'.startswith('ab')}")
print(f"'abcd'.startswith('x')={'abcd'.startswith('x')}")
# кінець рядка
print(f"'abcd'.endswith('cd')={'abcd'.endswith('cd')}")
print(f"'abcd'.endswith('x')={'abcd'.endswith('x')}")
# перехід від списку рядків до одного рядка
print(f"'[X]'.join(['abcd', '123', 'èéà'])={'[X]'.join(['abcd', '123', 'èéà'])}")
print(f"''.join(['abcd', '123', 'èéà'])={''.join(['abcd', '123', 'èéà'])}")
# перехід від рядка до списку рядків
print(f"'abcd 123 cdXY'.split('cd')={'abcd 123 cdXY'.split('cd')}")
# отримати слова з рядка
print(f"'abcd 123 cdXY'.split(None)={'abcd 123 cdXY'.split(None)}")

Коментарів у поєднанні з отриманими результатами достатньо для розуміння скрипту. Результати такі:


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
'cheval[2]=e
'символи з діакритичними знаками'[5:7]=tè
'символи з діакритичними знаками'[4:]=символи з діакритичними знаками
'символи з діакритичними знаками'[:5]=символи
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. Скрипт [str_03]: кодування рядків (1)

Скрипт [str_03] знайомить з поняттями кодування символьних рядків:


# кодування символів

# рядок типу str
str = "hélène va au marché acheter des légumes"
print(f"str=[{str}, type={type(str)}]")
# кодування utf-8
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)}")
# кодування 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)}")
# кодування 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)}")

Кодування символьного рядка типу <str> створює двійковий рядок, у якому кожен символ рядка представлений одним або кількома байтами. Існують різні типи кодування. У наведеному вище скрипті представлені два найпоширеніші в західному світі типи: «utf-8» та «iso-8859-1», також відомий як «latin1».

Принцип кодування/декодування проілюстровано нижче (див. |https://realpython.com/python-encodings-guide/ |):

Image

Коментарі

  • рядки 4–5: початковий рядок символів, який буде кодовано. Інстанції типу <str> — це рядки в форматі Unicode |https://docs.python.org/3/howto/unicode.html|, |https://realpython.com/python-encodings-guide/ |;
  • рядки 6–11: два способи кодування рядка символів у форматі UTF68:
    • рядок 8: str.encode('utf-8) ;
    • рядок 10: bytes(str, 'utf-8');
  • рядки 12–17: те саме повторюємо з кодуванням «iso-8859-1»;
  • рядки 18–23: «latin1» — це інша назва кодування «iso-8859-1»;

Результати такі:


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

Коментарі

  • рядок 4: бачимо, що символи з діакритичними знаками були закодовані двома байтами:
    • é: [\xc3\xa9], що є двійковим послідовністю 11000011 10101001;
    • è: [\xc3\xa8], що відповідає двійковій послідовності 11000011 10101000;
  • рядки 7: у кодуванні iso-8859-1 ці два символи з діакритичними знаками кодуються по-різному:
    • é: [\xe9], що відповідає двійковій послідовності 11101001;
    • è: [\xe8], що є двійковим послідовністю 11101000;

4.4. Скрипт [str_04]: кодування символьних рядків (2)

Скрипт [str_04] представляє ще два типи кодування: «base64» та «quoted-printable». Ці два типи кодування кодують не Unicode-рядки, а бінарні об’єкти. Наприклад, коли до електронного листа додають документ Word, він піддається одному з цих двох типів кодування залежно від використовуваного поштового клієнта. Це стосується більшості вкладених файлів.

Скрипт виглядає так:


# кодування / декодування
import codecs

# рядок
print("---- chaîne unicode")
str1 = "hélène va au marché acheter des légumes"
print(f"str1=[{str1}], type(str1)={type(str1)}")

# кодування utf-8
print("---- chaîne unicode -> binaire utf-8")
bytes1 = bytes(str1, "utf-8")
print(f"bytes1=[{bytes1}], type(bytes1)={type(bytes1)}")

# декодування utf-8
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}")

# кодування 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)}")

# декодування 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}")

# помилка декодування — bytes1 у форматі utf-8 — декодується у формат iso-8859-1
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 рядка Unicode
print("---- chaîne unicode -> binaire utf-8")
bytes3 = codecs.encode(str1, "utf-8")
print(f"bytes3=[{bytes3}], type(bytes3)={type(bytes3)}")

# кодування бінарного рядка UTF-8 у base64
print("---- binaire utf-8 -> binaire base64")
bytes4 = codecs.encode(bytes1, "base64")
print(f"bytes4=[{bytes4}], type(bytes4)={type(bytes4)}")

# повернення до вихідного Unicode-рядка
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)}")

# кодування бінарного рядка у форматі quoted-printable
print("---- binaire utf-8 -> binaire quoted-printable")
str7 = codecs.encode(bytes1, "quoted-printable")
print(f"str7=[{str7}], type(str7)={type(str7)}")

# повернення до вихідного рядка Unicode
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)}")

Коментарі

  • рядок 2: модуль [codecs] дозволяє виконувати кодування «base64» та «quoted-printable». Він може виконувати ще багато інших;
  • рядки 4–7: Unicode-рядок, який піддається різним кодуванням;
  • рядки 9–12: кодування utf-8. Отримуємо бінарний файл;
  • рядки 14–18: декодування у форматі utf-8 для повернення до вихідного рядка Unicode;
  • рядки 20–29: повторюється той самий процес із кодуванням «iso-8859-1»;
  • рядки 31–34: демонструється помилка декодування:
  • рядок 33: bytes1 — це бінарний рядок, закодований у форматі «utf-8». Його декодують у формат «iso-8859-1»;
  • рядки 36–39: інший спосіб кодування символьного рядка у форматі utf-8 за допомогою модуля [codecs];
  • рядки 41–44: бінарний рядок «utf-8» кодується у «base64»;
  • рядки 46–49: демонструють, як перейти від бінарного рядка «base64» до вихідного рядка Unicode;
  • рядки 51–59: цей процес повторюється з кодуванням «quoted-printable» замість «base64»;

Результати такі:


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
  • рядки 14–15: бінарний UTF-8 декодується в рядок Unicode за допомогою неправильного декодера «iso-8859-1». Тому деякі згенеровані символи Unicode є неправильними, у даному випадку це символи з діакритичними знаками;
  • рядки 18–19: кодування «base64» полягає у використанні 64 символів ASCII (закодованих у 7 бітах) для кодування будь-якого бінарного файлу. Це, як бачимо, збільшує розмір бінарного файлу в рядку;
  • рядки 22–23: кодування «quoted-printable» також полягає у використанні символів ASCII (кодованих у 7 бітів) для кодування будь-якого бінарного файлу;

Слід пам’ятати, що коли ми отримуємо бінарний файл, наприклад з Інтернету, який представляє текст, для його відновлення необхідно знати, яким кодуванням він пройшов.