Строки (подробнее) по Марку Лутцу

Всем доброго вечера, кто читает мои небольшие публикации. Сегодня я наконец-то перехожу освещать седьмую по счёту главу книги Марка Лутца «Изучаем Python». Данная статья посвящена глубокому анализу строк и методов работы с ними.

Строки (подробнее) по Марку Лутцу

Итак, что же по сути является строкой с точки зрения Python?

Строка - это тип данных, представляющий упорядоченную коллекцию символов для хранения и текстовой и байтовой информации.

В Python строки обычно представлены с помощью одинарных кавычек (''), двойных кавычек ( '' ''), тройных кавычек (''' '''). Строковый тип дынных представлен классом str()

myString = 'Misha' myNewString = "Misha" myNewNewString = """Misha""" print(myString, myNewString, myNewNewString) #Misha Misha Misha print(type(myString), type(myNewString), type(myNewNewString)) # <class 'str'> <class 'str'> <class 'str'>

Марк Лутц начинает введение в строковый тип данных с получение представления у читателя о кодировки информации. Вообще кодировок существует большое множество, однако наибольшей популярностью используются Unicode и ASCII

Что вообще такое кодировки и как с ними работать?

Пожалуй, не для кого не секрет, что элемент строки является символ. Например, буквы английского алфавита - это один набор символов, буквы русского алфавита - другой набор символов. То же самое можно сказать и про китайский, арабский и другие языки и компьютеру надо с ними работать. И поэтому для их обработки придумали специальную систему кодировки.

В своей книге Лутц останавливается на Unicode и ASCII.

«ASCII - это простая форма текста Unicode, но лишь одна из немногих кодировок алфавита»

М.Лутц

В Python содержится аж три строковых типа. Один из них я уже называл (str, для текста), вместе с ним имеется bytes(для двоичных данных), bytearray (изменяемый вариант типа bytes).

Отличие двух кодировок определяется шагом трансляции. Он необходим для получения данных из файлов. Практический пример использования кодировки можно встретить например в библиотеке pandas. Например, если при импорте данных из того же excel-файла не правильно указать кодировку, то вывод данных будет не читаемым для человека (пожалуй всем известен случай с «крокозябрами»).

Что предлагает автор знать на начальном этапе о строках?

1) Строки допускается использовать для представления всего что может восприниматься как текст или байты

2) Строки - это инструмент высокого уровня. Они сопровождаются большим количеством методов их обработки.

3) Строки - неизменяемая последовательность и их значение не поддаётся каким-либо модификациям. Поэтому, чтобы модифицировать строку, необходимо создать новую строку на основе предыдущей.

4) Для сложной обработки строк можно пользоваться библиотекой re. Этой библиотеке посвящу публикацию отдельно.

О том, что можно творить со строками можно узнать как из книги, так и из официальной документации. Для ознакомления со всеми методами можно пройти по следующей ссылке.

Как ещё можно представить строки ( примеры)?

print("s\tp\na\0\m") # Вывод - управляющие последовательности s p a print(r"C:\new\test.spm") # Вывод - неформатированные строки C:\new\test.spm print(b'sp\x01am') # Вывод - байтовые литералы b'sp\x01am' print(u'eggs\u0020spam') # Вывод - литералы Unicode eggs spam

Однако самые распространённые случаи считаются представление строкового типа с помощью одинарных и двойных кавычек.

С точки зрения Python они почти ничем не отличаются друг от друга, поэтому прежде чем начать писать проект, вы договоритесь сами с собой какие кавычки вы будете использовать.

И ещё примеры:

'myString', 'myString2' #('myString', 'myString2') 'Mikhail"s', "Allex's" #('Mikhail"s', "Allex's") message = "I " 'am' " filling good" # I am filling good 'Mikhail\'s', "Allex\"s" # ("Mikhail's", 'Allex"s') Тут кавычка внедряется во внутрь строки

В последней строки используются символы с обратной косой чертой (\). Данный символ используется для изменения представления выводимой строки в интерпретаторе. Я достаточно часто использовал символ \n на сайте CodeWars, однако вместе с ним есть и ряд других. Ниже представлю перечень.

\новая строка - Игнорируется (строка продолжения)

*\\ - Обратная косая черта (сохраняет символ \)

*\' - Одинарная кавычка (сохраняет ')\'' - Двойная кавычка (сохраняет '')

\a - Звонок

\b - Забой

\f - Перевод страницы

\n - Новая строка

*\r - возврат коретки

\t - горизонтальная табуляция

\v - вертикальная табуляция

\xhh - шестнадцатиричный символ

\ooo - символ с восьмиричным значением

\O - пустой двоичный символ (не конец строки)

\N{идентификатор} - Идентификатор Unicode

\uhhhh - Символ Unicode c 16-битным шестнадцатиричным значением

\Uhhhhhhh - Символ Unicode с 32-битным шестнадцатеричным значением


* Используются в программировании достаточно часто

Стоить также указать, что функция len() , отвечающая за вывод количество символов НЕ учитывает вышеописанные специфические значения.

newString = 'T\nis\t is \n\aspam' strng = 'This is is spam' print(len(newString), len(strng)) # 15 15

Такое поведения программы обязательно следует учитывать при проектировании приложения.

Замечание

Существуют примеры, когда ввод специальных символов вызывает затруднение. Например, они могут возникнуть, когда путь файла содержит символы, которые не следует считать как символы. Тогда для решения подобной задачи может помочь флаг r. Вот пример:

myFilePath = '\new\text.dat' print(myFilePath) # ew ext.dat print(len(myFilePath)) #11

Совсем не то, что я хотел вывести. Я ожидал, что вызов print() выведет мне полный путь файла. Поэтому, чтобы это исправить, немного модифицируем код вот так:

myFilePath = r'\new\text.dat' print(myFilePath) #\new\text.dat print(len(myFilePath)) #13

Мы всего лишь добавили флаг r к '\new\text.dat' и у нас получилась требуемая строка.

Обратите внимание на это правило!

Тройные кавычки

Говоря простым языком, если двойные кавычки от одинарных практически ничем не отличаются, то с помощью тройных может описываться документирование кода. В тройных кавычках уже могут автоматически содержаться специфические символы, даже если формально они не встречаются в тексе. Вот пример:

life = """ The best day of my life """ life # '\nThe\nbest\nday\nof\nmy life\n\n' print(life) # Однако: #The #best #day #of #my life

С помощью тройных кавычек можно:

1) Выделять код

2) Документировать программу

3) Описывать состояние ошибок

Однако на практике, чем меньше мы используем документирование в программе тем лучше. Сейчас будет отсылка на мою статью на хабре: https://habr.com/ru/post/683956/

Что умеют строки в Python? Базовые операции

1) Считать длину

myString = 'Misha' print(myString) # Misha print(len(myString)) #5

2) Конкатенация:

myString = 'Misha' secondString = ' Ivashkin' print(myString+secondString) # Misha Ivashkin

3) Повторение

myString = 'Misha' secondString = ' Ivashkin ' print((myString+secondString) * 4) # Misha Ivashkin Misha Ivashkin Misha Ivashkin Misha Ivashkin

4) Индексация:

myString = 'Misha' secondString = ' Ivashkin ' initials = myString+secondString print(initials[0:5]) # Misha

Индексация - это способ извлечения информации согласно номеру символа. Номер символа начинается с 0. Я не буду подробно останавливаться на этом, просто имейте ввиду, что она существует.

А теперь внимание!

Очень частая ошибка:

a = '34' print(a+2) # TypeError: can only concatenate str (not "int") to str

Почему так? На самом деле всё просто: у нас переменная a хоть и принимает значение 34, но она обёрнута в кавычки, поэтому интерпретатор распознаёт её как строку. А Python не позволяет складывать строку с числом.

Чтобы исправить, надо представить переменную в целочисленный тип данных

a = '34' print(int(a)+2) # 36

Преобразования кодов символов

Не смотря на то, что Лутц описывает это неявно, но существует представление о том, что каждый символ представляется определённым кодом. Он соответствует кодировке ASCII. По таблице видно, что каждое значение соответствует своему шестнадцатиричному и десятичному значению.

Строки (подробнее) по Марку Лутцу

Для их преобразования существуют методы ord() и chr() . Для понимания кодировки Лутц предлагает написать следующий код:

S = '5' chrS = ord(S) print(chrS) # 53

Если мы проверим решение на предмет соответствия с таблицей, то мы обнаружим, что действительно символ 5 соответствует числу 53. Python допускает операции с преобразованными значениями. Но, обратите внимание, только с числами закодированных символов.

Как можно изменять строку?

Поскольку нам известно о том, что строка является неизменяемым типом данных, а менять строку всё равно нужно, то чтобы это исправить существует три основных способа: конкатенация, замена символа и форматирование. Ниже привожу примеры

1) Конкатенация

s = 'spam' print(s+'SPAM!') # spamSPAM! s = 'spam' print(s[:4]+'SPAM!'+ s[4:]) # spamSPAM!

2) Замена символов

s = 'splot' s = s.replace('pl', 'pamal') print(s) # spamalot

3) Форматирование

A.

a='This is %d %s bird!' % (1, 'dead') print(a) # This is 1 dead bird!

Б.

a='This is {0} {1} bird!'.format(1 , 'dead') print(a) # This is 1 dead bird!

Методы, представленные в статье являются базовыми, однако их недостаточно для того, чтобы понять всё многообразие работы со строками. Для того, чтобы полностью увидеть картину можно заглянуть в документацию. Ссылку по строкам я уже сюда приводил, поэтому чтобы вы не забыли, продублирую её заново ( https://docs.python.org/3/library/stdtypes.html?highlight=str#str ). Настоятельно рекомендую потренироваться над изменением и способам проверки строк. Помните, что программирование - это больше про практику.

А теперь подробней про форматирование

Форматирование строк - способ, позволяющий выполнять множество подстановок, специфических для типов за единственный шаг.

М.Лутц

На сегодняшний день существует три способа форматирования текста, однако Лутц выделяет только два (очень сказывается время, когда впервые была выпущена эта книга). Пример использования f-строки я раскрывать не стану. Скажу лишь, что он сейчас наиболее популярный и часто используется в программировании.

Шаблон форматирования определяется с помощью базового шаблона

'….%s….' % (значение) - старый приём

'….{}…..'.format(значение) - новый приём

Эти два приёма необходимо знать вместе, поскольку в первый случай наиболее предпочтительней использовать, когда заходит речь о вставке данных в реляционную базу данных.

Пара примеров:

exclamation = 'Ni!' print('The knights who say %s!' % exclamation) # The knights who say Ni!! message = '%d %s %g you' % (1, 'spam', 4.0) print(message) # 1 spam 4 you messageNew = '%s -- %s -- %s' % (42, 3.14159, [1,2,3]) print(messageNew) # 42 -- 3.14159 -- [1, 2, 3]

Интерпретация и результаты:

Что такое % ? - ожидает в правой стороне либо одиночный элемент, либо кортеж из одного и более элементов.

Что такое %d, %s ? - это специальный код, описывающий вставляемые данные. Ниже представлен список из этих элементов

s - строка (или строка str(x) любого объекта)

*r - То же, что и s, но применяется как repr, а не strc - символ (int или str)

d - десятичное число (целое число с основанием 10)

*i - целое числоo - восьмиричное целое число

x - Шестнадцатиричное целое число

X - то же самое, что и в верхнем регистреe - число с плавающей точкой со степенью в нижнем регистре

E - то же, что и e, но в верхнем регистре

f - десятичное число с плавающей точкой

*F -то же, что и f, но в верхнем регистре

*g - число с плавающей точкой e или f

G - Число с плавающей точкой E или F

* - на мой взгляд часто используемые символы вставки

Если знать, когда применять кодировку, можно легко подобрать нужный текст, главное запомнить какой код за что отвечает

number = 1234 message = 'integers: ...%d...%-6d...%06d' % (number, number, number) print(message) # integers: ...1234...1234 ...001234

Обратите внимание на %06d в строке. По сути данный формат строки означает, что выводимое число должно содержать 6 целых чисел. Если мы посчитаем количество цифр в 001234, то как раз получим тот же самый ответ.

%-6d отвечает за выделенное пространство под число. Если количество чисел меньше, чем область, то он добавляет к ней знаки пробелов

x = 1.23456789 print(x) x = 1.23456789 message = '%e | %f | %g' % (x,x,x) print(message) # 1.234568e+00 | 1.234568 | 1.23457 message2 = '%-6.2f | %05.2f | %+06.1f' % (x,x,x)

Форматирование на словаре

Стоит иметь ввиду, что форматирование строк сильно отличается от форматирования словаря. Для того, чтобы отформатировать данные через словарь Лутц приводит следующий пример.

reply = """ Greetings... Hello %(name)s! Your age is %(age)s """ values = {'name': 'Misha', 'age':23} print(reply %values)

Важно: форматирование через словарь очень часто пригождается в работе с базами данных, поэтому настоятельно рекомендую потренироваться в использовании словарей при форматировании текста.

Форматирование через метод format()

Метод format() базируется на обычном синтаксисе вызова функции, а не выражении.

М.Лутц

Я не буду вдаваться здесь в теорию. Сразу перейду к практике

template = '{0}, {1} and {2}' template.format('spam', 'ham', 'eggs') #'spam, ham and eggs' newTemplate = '{motto}, {pork} and {food}' newTemplate.format(motto = 'spam', pork = 'ham', food='eggs') #'spam, ham and eggs'

Для словарей:

template = '%(motto)s, %(pork)s and %(food)s' template % dict(motto='spam', pork='ham', food = 'eggs') #'spam, ham and eggs'

Более сложные методы форматирования:

import sys 'My {1[kind]} runs {0.platform}'.format(sys, {'kind': 'laptop'}) #'My laptop runs win32'

В последнем примере используется индексация (позиция метода форматирования. Применяя ключи словаря и метод библиотеки sys получаем заветное слово:)

'My {map[kind]} runs {sys.platform}'.format(sys=sys, map = {'kind': 'laptop'}) #'My laptop runs win32'

Здесь показывается пример, аналогичный предыдущему, единственное, что бы я сделал - это поменял название словаря, уж очень он идентичен зарезервированному слову map ( смотрите доку )

myList = 'MyNewValue' 'first = {0[0]}, third = {0[2]}'.format(myList) #'forst = M, third = N

Есть ещё более специфические методы форматирования, но для собеседования, думаю, достаточно знать базовые

В заключении статьи опишу какие преимущества видит автор, применяя метод format

1) Располагает некоторыми дополнительными возможностями, отсутствующими в самом выражении

2) Обладает гибким синтаксисом ссылки на чтение

3) Может делать ссылки на значения более явными

4) Обменивает операцию на более значащее имя метода

5) Не допускает разного синтаксиса для одиночных и множественных значений

Строки (подробнее) по Марку Лутцу

В заключении могу сказать, что это не всё, что отразил в своей книге Лутц. В статье представлена только базовая и основная выжимка. Статья не раскрывает специфичные случаи использования строк, но может дать базовое представление о том, что это такое и как оно работает. Благодарю за внимание и до новой статьи!

Все статьи по книге собраны в отдельном сообществе на vc:

Кому интересно развитие проекта, могут поддержать донатами.

Спасибо за прочтение!

11
Начать дискуссию