Метка: strings

​​Unicode по имени

Вы знали, что в строке Python 3 можно вставлять символы по их названию в юникод-таблице?

Допустим нужны вам стрелки:

>>> "\N{LEFTWARDS ARROW} EXIT \N{RIGHTWARDS ARROW}"
'← EXIT →'

Найти юникод символы и их имена удобно с помощью онлайн-сервисов

Да, конечно, в Python 3 вы можете прямо в код вставлять любые юникод символы без их кодов и имен. Но профессиональнее – вставлять символы по именам, потому что читатель вашего кода может видеть его другим шрифтом, где начертание символов отличается от вашего, или вообще эти символы не отображаются. Ерунда? А вот вам пример:

>>> "Hello" == "Hello"
False

Строки выглядят одинаково, но я спрятал в одной из них символ "\N{ZERO WIDTH JOINER}", поэтому они неравны:

>>> len("Hel‍lo")
6
>>> len("Hello")
5
>>> "Hello".encode('utf-8')
b'Hel\xe2\x80\x8dlo'
>>> "Hello".encode('utf-8')
b'Hello'

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

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈 

Флаги преобразования

При форматировании строк доступны 3 флага преобразования объекта в строку: !r, !s и !a.

>>> x = "дом"
>>> f'{x}'
'дом'
>>> f'{x!r}'
"'дом'"
>>> f'{x!s}'
'дом'
>>> f'{x!a}'
"'\\u0434\\u043e\\u043c'"

Для фанатов format:

>>> '{0!r}'.format(x)
"'дом'"
>>> '{!r}'.format(x)
"'дом'"

Флаг !r вызывает repr(x), а флаг !s вызывает str(x). Флаг !a вызывает ascii(repr(x)). Функция ascii превращает все символы за пределами набора ASCII (включая русские буквы в юникоде) в их коды. Если флаг не указан, то по умолчанию считается, что он !s.

Для классов __repr__ и __str__ могут иметь различное определение:

class Foo:
    def __repr__(self):
        return "репр"
    def __str__(self):
        return "строка"
x = Foo()
print(f'{x!r}')  # репр
print(f'{x!s}')  # строка

Если __str__ нет, то будет вызван __repr__.

Рекомендации: __str__ должен давать нам человеко-читаемое описание объекта, а __repr__ – уникальное представление объекта, по которому можно частично или полностью восстановить состояние этого объекта или хотя бы помочь с отладкой. __str__ – для пользователей, __repr__ — для питонистов.

📎 Отличный пример для наглядности – datetime:

>>> import datetime
>>> dt = datetime.datetime(2019, 7, 27)
>>> repr(dt)
'datetime.datetime(2019, 7, 27, 0, 0)'
>>> str(dt)
'2019-07-27 00:00:00'
>>> eval(repr(dt)) == dt
True

str от datetime просто покажет нам дату и время в удобном формате; repr от datetime вернет строку, в которой будет вызов описан конструктора конкретно этого объекта, да так, что при исполнении этой строки как кода на Python функцией eval – мы получим объект datetime для той же даты. Впрочем, никто нас не обязывает делать этот трюк для каждого объекта.

🐉 Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈