Comments 40
>>> a = 'dog'
>>> b = 'dog'
>>> a is b # id(a) == id(b)
True
>>> a += ' cat'
>>> a
'dog cat'
>>> b
'dog'
>>> a is b
False
Кстати, немного удивил этот способ экономии памяти на одинаковых строках. Но уверен у разработчиков python есть аргументы почему это сделано так.
string interning, реализовано во многих языках
Да, но в python это распространяется на все неизменяемые объекты
>>> import sys
>>> sys.getrefcount(1)
815
>>> sys.getrefcount(0)
1215
>>> sys.getrefcount('')
455
>>> sys.getrefcount(())
8771
В Java точно так же. Строки неизменяемые, и литералы хранятся в специальной области хипа (heap), называемой String Pool.
В момент присвоения строкового литерала компилятор ищет такую же строку в String Pool и возвращает ссылку на существующий объект либо создаёт новый. Это называется "интернирование" (interning).
Следует, однако, различать литералы и строки, созданные с использованием оператора new. Во втором случае всегда создаётся новый объект в куче (не в String Pool). К тому же у строк есть метод intern(), но детали здесь не буду приводить.
По 37. Чего-то пример вообще не в тему.
ИМХО, правильней проверка так:
proverb = 'Rise each day before the sun'
id(proverb) # -> 5691328
proverb += 'b'
id(proverb) # -> 7467712
Намного изящней смотрится способ с переворотом строки срезом:
print("hello world"[::-1]) # dlrow olleh
Задачу удобно решать перейдя от строки к множествам
first_str = 'aabbcdef'
second_str = "cdefghhh"
first_set = set(first_str) # символы без повторов
second_set = set(second_str) # символы без повторов
print(first_set, second_set)
# {'c', 'a', 'd', 'e', 'f', 'b'} {'c', 'g', 'd', 'e', 'h', 'f'}
# Определеим пересечение и объединение
intersection_set = first_set & second_set # пересечение
union_set = first_set | second_set # объединение
print(intersection_set, union_set)
# {'c', 'd', 'e', 'f'} {'c', 'a', 'd', 'g', 'e', 'h', 'f', 'b'}
# вернемся к сортированным строкам
intersection_str = ''.join(sorted(intersection_set))
union_str = ''.join(sorted(union_set))
print(intersection_str, union_str) # cdef abcdefgh
Еще распространенная задача — выделение из текста отдельных слов.
Вот пример решения регулярным выражением — stackoverflow.com/questions/6181763/converting-a-string-to-a-list-of-words
В 23 пункт по срезам добавьте, что step может быть отрицательным, и тогда перебор идет в обратном порядке, от конца к началу — это иногда очень удобно, например как в моем примере выше с переворотом строки.
>>> import re
>>> string = 'Hello 1 World 2'
>>> re.sub(r'[aeiou]', '', string)
'Hll 1 Wrld 2'
Ещё есть интересный метод — rsplit(разбивает строку справа налево). Буквально на днях понадобилось мне разбить строки вида «1:2:3:4:5:data» по последнему разделителю. Сначала пробовал так «str.split(':',-1)» — не получилось. Погуглил — нашел rsplit. Да, это есть в офф. документации. Но в процессе гугления понял, что много народа об этом не знают.
41 тривиальный ответ на бестолковые вопросы о том о сём.
Вы бы уж до 42 дотянули, что ли…
Мне кажется вопросов действительно о строках тут мало. Тут многое про множества, парадигмы протоколов… но как-то неявно, неглубоко.
К примеру, интересно было бы упомянуть про различие между isdigit, isnumeric и isdecimal хотя бы в виде ссылки. Это может оказаться любопытным.
Также часто новички путаются со строковыми литералами в коде.
a = 'это '\
'одна строка'
b = ('а кто '
f'{random.choice(["не ", ""])}угадает '
'что здесь присвоится?'
)
Про юникод-символы много всякого можно рассказать вроде такого:
'копе\N{combining acute accent}йка \N{RUBLE SIGN} бережет'
difficulty = 'easy'
thing = 'exam'
'That {thingy} was {how_hard}!'.format(thingy=thing, how_hard=difficulty)
#=> 'That exam was easy!'
''.join([c for c in string if c not in vowels])
А зачем тут список делать, если достаточно просто итерируемого объекта? Просто generator expression будет достаточно: ''.join(c for c in string if c not in vowels)
как раз сейчас учу пайтон, спасибо, за суперинформативный для меня лично пост)
Пункт 35. Как объединить две строки
'string one' + ' ' + 'string two'
Зачем делать действие в таком виде? А если нужно будет сложить десяток строк? Конкатенация для каждого из плюсов создаёт промежуточный объект и является самым медленным способом работы со строками.
В данном случае лучше использовать либо метод " ".join()
, куда вставить список строк для объединения, либо использовать упомянутый в пункте 8 синтаксис f-строк: f"{} {}"
.
s = "Test string"
print(s[::-1]) # gnirts tseT
Для того чтобы «перевернуть» строку, её можно разбить, представив в виде списка символов, «перевернуть» список, и, объединив его элементы, сформировать новую строку.
'hello world'[::-1]
А так спасибо автору, хотя с некоторыми примерами не согласен
—
Есть 3 метода определения состоит ли строка лишь из цифр:
isnumeric(), isdigit(), isdecimal()
На символы неарабских цифр или дробей они дают разные ответы.
Если проверка именно на арабские цифры, то лучше использовать isdecimal()
vals = ("038", "੦੩੮", "038",
"⁰³⁸", "⒊⒏", "⓪③⑧",
"↉⅛⅘", "ⅠⅢⅧ", "⑩⑬㊿", "壹貳參",
"38.0", "-38"
)
for s in vals:
print(s, s.isnumeric(), s.isdigit(), s.isdecimal())
''.join(c for c in string if c not in vowels)
>>> string = 'Hello 1 World 2'
>>> mapping = str.maketrans("", "", "aeiou");
>>> string.translate(mapping)
'Hll 1 Wrld 2'
32. Как узнать о том, что строка включает в себя только пробелы?
Не пробелы, а пробельные символы (whitespace).
>>> '\r \n'.isspace()
True
Для объединения строк можно воспользоваться оператором +.
'string one' + ' ' + 'string two'
#=> 'string one string two'
Пример неудачен, со строковыми литералами это делать бессмысленно, можно обойтись без плюсов:
>>> 'string one' ' ' 'string two'
'string one string two'
Стоит добавить что в py3.9 у строк есть весьма полезные методы .removeprefix() и .removesuffix()
41 вопрос о работе со строками в Python