1.6 Строки как объекты#

Объекты, атрибуты, методы#

Прежде чем продолжить рассмотрение функционала строк, нам понадобится ещё раз остановиться на объектах. Мы уже несколько раз говорили, что в Python все является объектами, и наша программа просто описывает последовательность взаимодействий между объектами. Давая определение объекту, мы можем сказать, что это некоторая абстракция данных, которую характеризуют:

  1. Идентификатор - позволяет отличить один объект от другого

  2. Тип данных - описывает поведение объекта, какие операции с ним можно выполнить

  3. Значение - сами данные, записанные в объекте

У любого объекта достаточно просто обратиться к его идентификатору или типу данных:

id("string as object")  # идентификатор - место в памяти, где хранится объект
139976413143280
type("string as object")  # тип данных
str

Чуть сложнее дело обстоит со значением объекта. Например, для численных типов данных значением объекта будет само число, которое мы указали при определении объекта. Но для некоторых типов данных значение может быть более сложным и состоять из набора атрибутов и методов. Атрибуты мы можем определить как переменные, сохраненные внутри объекта, а методы - как атрибуты, которые мы можем ещё и вызвать, то есть функции, сохраненные внутри объекта. Функциями в свою очередь мы будем называть сохраненную последовательность инструкций, к которой мы можем обратиться по имени, как будто это переменная, и которую мы можем вызвать - выполнить.

Так, значение для объекта строки будет складываться из последовательности символов, а также набора атрибутов и методов, соответствующих типу данных строки. Чтобы обратиться к атрибуту объекта, достаточно после объекта поставить точку и написать имя нужного атрибута:

my_string = "Hello, world"

my_string.upper  # Так мы обратимся к атрибуту upper и узнаем, что это на самом деле функция
                 # Функция - блок кода, который может быть вызван из других частей программы
<function str.upper()>
"Hello, world".upper
<function str.upper()>

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

my_string.upper()
'HELLO, WORLD'

Методы строк#

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

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

  1. str.upper() - преобразование строки в верхний регистр

"Hello, world".upper()
'HELLO, WORLD'
  1. str.lower() - преобразование строки в нижний регистр

"Hello, world".lower()
'hello, world'
  1. str.capitalize() - преобразование первой буквы строки в верхний регистр, остальных букв в нижний

"Hello, world".capitalize()
'Hello, world'
  1. str.title() - преобразование каждого слова в строке так, чтобы первая буква была в верхнем регистре, остальные в нижнем

"Hello, world".title()
'Hello, World'

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

  1. str.startswith() - проверка, начинается ли строка с заданной подстроки

"Hello, world".startswith("Hello")
True
  1. str.endswith() - проверка, заканчивается ли строка заданной подстрокой

"Hello, world".endswith("world")
True

Ещё одной из наиболее частых задач является выполнение замены подстроки в строке.

  1. str.replace(a, b) - заменяет все вхождения a в str на b

Просто вызвать replace нельзя, обязательно нужно указать, что и на что меняем: 'объект строки'.replace('что нужно заменить', 'на что нужно заменить')

"Hello, world".replace("Hello", "Goodbye")
'Goodbye, world'

Ранее мы уже видели, как работает конкатенация - объединение строк. Для обратного действия есть специальный метод.

  1. str.split(a) - разбивает строку str по разделителю a

В данном случае разделитель a указывать не обязательно. Так, при вызове split без дополнительных параметров будет считаться, что мы пытаемся разбить строку по всем пробельным символам.

"Hello, world".split()
['Hello,', 'world']

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

"Hello, world".split(", ")
['Hello', 'world']

Последовательное выполнение методов

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

"Hello, world".lower().replace('hello', 'hi')
hi, world

Приведение типов#

Ранее мы уже говорили, что типы (int, float) — это тоже объекты в Python. Тип str — не исключение. Как и другие типы, его можно вызвать, и при вызове он попытается преобразовать переданный аргумент к строке:

В целом к строке можно привести что угодно:

str(3.14)
'3.14'

Чуть интереснее посмотреть, как работают обратные приведения, когда из строки нужно получить число. Сами типы int и float работают так же, как str — это объекты, которые можно вызвать:

  1. К целому числу можно привести только ту строку, которая выглядит соответственно правилам объявления обычного целого числа

int('10')
10
int('1_000_000')
1000000
  1. Аналогичное правило работает для дробных чисел

float('3.14')
3.14
  1. К логическому типу можно привести любую строку. Если строка содержит хоть один символ (даже пробельный), то будет возвращено значение True, для абсолютно пустой строки - False. Похожим образом это будет работать и для других типов данных - False возвращается только для нулевых значений, пустых объектов.

bool('Some text')
True
bool(' ')
True
bool('')
False

Форматирование строк#

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

f-строки (рекомендуемый способ)#

Начиная с Python 3.6, наиболее удобный и рекомендуемый способ — f-строки. Перед открывающей кавычкой ставится префикс f, а значения переменных подставляются в фигурных скобках:

lat = 55.75
lon = 37.62

f"Широта: {lat}, Долгота: {lon}"
'Широта: 55.75, Долгота: 37.62'

Внутри фигурных скобок можно использовать выражения и форматирование:

radius = 10
area = 3.14159 * radius ** 2

f"Площадь: {area:.2f} км²"  # :.2f — округление до 2 знаков после запятой
'Площадь: 314.16 км²'

Вычисления также можно делать, но обычно не рекомендуется — это ухудшает читаемость кода:

radius = 10

f"Площадь: {3.14159 * radius ** 2:.2f} км²"  # работает, но хуже читается
'Площадь: 314.16 км²'

Метод .format()#

До появления f-строк использовался метод .format(). Он работает в любом Python, но менее удобен:

"Широта: {}, Долгота: {}".format(lat, lon)
'Широта: 55.75, Долгота: 37.62'

Оператор %#

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

"Широта: %s, Долгота: %s" % (lat, lon)
'Широта: 55.75, Долгота: 37.62'