В Python строки - это последовательности символов, которые фактически
хранятся в памяти как объект. Каждый объект можно идентифицировать с
помощью id()
, как вы можете видеть ниже. Python пытается повторно
использовать объекты в памяти с одинаковым значением, что также
позволяет очень быстро сравнивать объекты в Python:
$ python
Python 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = "abc"
>>> b = "abc"
>>> c = "def"
>>> print (id(a), id(b), id(c))
(139949123041320, 139949123041320, 139949122390576)
>>> quit()
Для сравнения строк Python предлагает несколько разных операторов.
Сначала мы объясним их более подробно ниже. Во-вторых, мы рассмотрим как
string
и re
, которые содержат методы для обработки неточных
совпадений без учета регистра. В-третьих, для работы с многострочными
строками очень удобен модуль
difflib . Ряд примеров
поможет вам понять, как их использовать.
Операторы == и! =
В качестве основного оператора сравнения вы захотите использовать ==
и
!=
. Они работают точно так же, как и с целыми числами и значениями с
плавающей запятой. Оператор ==
возвращает True
если есть точное
совпадение, в противном случае будет возвращено False
Напротив,
оператор !=
True
если совпадений нет, а в противном случае
возвращает False
. Листинг 1 демонстрирует это.
В for
строка, содержащая название швейцарского города «Лозанна»,
сравнивается с записью из списка других мест, и результат сравнения
выводится на стандартный вывод.
Листинг 1:
# define strings
listOfPlaces = ["Berlin", "Paris", "Lausanne"]
currentCity = "Lausanne"
for place in listOfPlaces:
print ("comparing %s with %s: %s" % (place, currentCity, place == currentCity))
Запустив сценарий Python сверху, вы получите следующий результат:
$ python3 comparing-strings.py
comparing Berlin with Lausanne: False
comparing Paris with Lausanne: False
comparing Lausanne with Lausanne: True
Операторы ==
и is
Python имеет два оператора сравнения ==
и is
. На первый взгляд они
кажутся одинаковыми, но на самом деле это не так. ==
сравнивает две
переменные на основе их фактического значения. Напротив, is
сравнивает
две переменные на основе идентификатора объекта и возвращает True
если
две переменные относятся к одному и тому же объекту.
Следующий пример демонстрирует это для трех переменных с целыми
значениями. Две переменные a
и b
имеют одинаковое значение, и Python
обращается к одному и тому же объекту, чтобы минимизировать
использование памяти.
>>> a = 1
>>> b = 1
>>> c = 2
>>> a is b
True
>>> a is c
False
>>> id(a)
10771520
>>> id(b)
10771520
Как только значение изменится, Python повторно создаст объект и назначит
переменную. В следующем фрагменте кода b
получает значение 2, а затем
b
и c
относятся к одному и тому же объекту.
>>> b = 2
>>> id(b)
10771552
>>> id(c)
10771552
Эмпирическое правило , которому надо следовать , чтобы использовать ==
при сравнении неизменных типов (например , Интс) и is
при сравнении
объектов.
Дополнительные операторы сравнения
Для сравнения лексикографического порядка вы можете использовать
операторы сравнения <
, >
, <=
и >=
. Само сравнение проводится
посимвольно. Порядок зависит от порядка символов в алфавите. Этот
порядок зависит от таблицы символов, которая используется на вашем
компьютере при выполнении кода Python.
Имейте в виду, что порядок чувствителен к регистру. Например, латинский алфавит: «Автобус» стоит перед «автобусом». В листинге 2 показано, как эти операторы сравнения работают на практике.
Листинг 2:
# define the strings
listOfPlaces = ["Berlin", "Paris", "Lausanne"]
currentCity = "Lausanne"
for place in listOfPlaces:
if place < currentCity:
print ("%s comes before %s" % (place, currentCity))
elif place > currentCity:
print ("%s comes after %s" % (place, currentCity))
else:
print ("%s is similar to %s" % (place, currentCity))
Запустив сценарий Python сверху, вы получите следующий результат:
$ python3 comparing-strings-order.py
Berlin comes before Lausanne
Paris comes after Lausanne
Lausanne is similar to Lausanne
Сравнение без учета регистра
В предыдущих примерах основное внимание уделялось точному совпадению
строк. Чтобы позволить сравнения без учета регистра, Python предлагает
специальные строковые методы, такие как upper()
и lower()
. Оба они
напрямую доступны как методы соответствующего строкового объекта.
upper()
преобразует всю строку в прописные буквы, а lower()
в
строчные буквы соответственно. В следующем листинге, основанном на
листинге 1, показано, как использовать метод lower()
.
Листинг 3:
# using the == operator
listOfPlaces = ["Berlin", "Paris", "Lausanne"]
currentCity = "lausANne"
for place in listOfPlaces:
print ("comparing %s with %s: %s" % (place, currentCity, place.lower() == currentCity.lower()))
Результат выглядит следующим образом:
$ python3 comparing-strings-case-insensitive.py
comparing Berlin with lausANne: False
comparing Paris with lausANne: False
comparing Lausanne with lausANne: True
Использование регулярного выражения
Регулярное выражение - или для краткости «регулярное выражение» - определяет определенный шаблон символов. Что касается этой темы, Джеффри Фридл написал отличную книгу под названием « Освоение регулярных выражений»{.amazon-link} , которую я очень рекомендую.
Чтобы использовать этот механизм в Python, сначала импортируйте модуль re, а затем определите конкретный шаблон. Опять же, следующий пример основан на листинге 1 . Шаблон поиска соответствует «заливу» и начинается со строчной или прописной буквы. А именно, следующий код Python находит все строки, в которых встречается шаблон поиска, независимо от того, в какой позиции строки - в начале, в середине или в конце.
Листинг 4:
# import the additional module
import re
# define list of places
listOfPlaces = ["Bayswater", "Table Bay", "Bejing", "Bombay"]
# define search string
pattern = re.compile("[Bb]ay")
for place in listOfPlaces:
if pattern.search(place):
print ("%s matches the search pattern" % place)
Результат выглядит следующим образом и соответствует "Bayswater", "Table Bay" и "Bombay" из списка мест:
$ python3 comparing-strings-re.py
Bayswater matches the search pattern
Table Bay matches the search pattern
Bombay matches the search pattern
Многострочные и списковые сравнения
Пока что наши сравнения касались лишь нескольких слов. Использование
difflib
Python также предлагает способ сравнения многострочных строк и
целых списков слов. Вывод может быть настроен в соответствии с
различными форматами инструментов сравнения.
Следующий пример ( листинг 5 ) сравнивает две многострочные строки
построчно и показывает как удаления, так и добавления. После
инициализации Differ
в строке 12 сравнение выполняется с помощью
compare()
в строке 15. Результат выводится на стандартный вывод
(строка 18).
Листинг 5:
# import the additional module
import difflib
# define original text
# taken from: https://en.wikipedia.org/wiki/Internet_Information_Services
original = ["About the IIS", "", "IIS 8.5 has several improvements related", "to performance in large-scale scenarios, such", "as those used by commercial hosting providers and Microsoft's", "own cloud offerings."]
# define modified text
edited = ["About the IIS", "", "It has several improvements related", "to performance in large-scale scenarios."]
# initiate the Differ object
d = difflib.Differ()
# calculate the difference between the two texts
diff = d.compare(original, edited)
# output the result
print ('\n'.join(diff))
Запуск сценария создает результат, как показано ниже. Строки с
удалениями обозначаются -
тогда как строки с добавлением начинаются со
знака +
Кроме того, строки с изменениями начинаются с вопросительного
знака. Изменения обозначаются ^
в соответствующей позиции. Линии без
индикатора все те же.
$ python comparing-strings-difflib.py
About the IIS
- IIS 8.5 has several improvements related
? ^^^^^^
+ It has several improvements related
? ^
- to performance in large-scale scenarios, such
? ^^^^^^
+ to performance in large-scale scenarios.
? ^
- as those used by commercial hosting providers and Microsoft's
- own cloud offerings.
Заключение
В этой статье вы узнали о различных способах сравнения строк в Python. Мы надеемся, что этот обзор поможет вам эффективно программировать в жизни вашего разработчика.
Благодарности
Автор благодарит Мэнди Ноймайер за поддержку при подготовке статьи.