Перейти до вмісту
> 💻 🧠 Код 1001 > 📑 Шпаргалки > 🐍 Шпаргал > Маловідомі можливості f-рядків, про які ви могли не знати

Маловідомі можливості f-рядків, про які ви могли не знати

<em># Створюємо дві змінні з числовими значеннями.</em>
one = 1
two = 2

<em># Вставляємо значення змінних 'one' та 'two' в рядок.</em>
f"{one}, {two}"
<em># Вивід: '1, 2'</em>

Сила f-рядків полягає в їхній здатності містити не просто змінні, а практично будь-який валідний вираз Python всередині дужок. Це дозволяє виконувати обчислення «на льоту», не створюючи непотрібних проміжних змінних.

<em># Виконуємо додавання безпосередньо всередині f-рядка.</em>
f"{one} + {two} = {one + two}"
<em># Вивід: '1 + 2 = 3'</em>

Ви можете легко звертатися до елементів структур даних, таких як словники (за ключем) та списки (за індексом), з f-рядка. Це також стосується доступу до атрибутів об’єктів (за допомогою крапкової нотації) і навіть виклику функцій.

<em># Доступ до значення словника за ключем.</em>
colors = {"red": "#ff0000", "green": "#00ff00"}
f"Червоний колір: {colors['red']}"
<em># Вивід: 'Червоний колір: #ff0000'</em>

<em># Доступ до елементів списку за індексом.</em>
data = [4, 8, 15, 16, 23, 42]
f"Найкращі числа: {data[4]} та {data[5]}"
<em># Вивід: 'Найкращі числа: 23 та 42'</em>

<em># Доступ до атрибутів об'єкта та виклик функцій.</em>
from dataclasses import dataclass
@dataclass
class Point:
    x: int
    y: int
pos = Point(23, 42)
f"Позиція: {pos.x}, {pos.y}. Більше значення: {max(pos.x, pos.y)}."
<em># Вивід: 'Позиція: 23, 42. Більше значення: 42.'```</em>

---

<em>### Використання f-рядків для налагодження</em>

Починаючи з Python 3.8, f-рядки отримали потужний інструмент для швидкого налагодження. Додавши знак рівності (`=`) після змінної або виразу в фігурних дужках, ви вказуєте Python вивести не тільки значення, але й сам вираз. Це неймовірно зручно для інспекції коду.

```python
from datetime import date, timedelta
user = "eric_idle"
member_since = date(1975, 7, 31)
delta = date(2022, 4, 11) - member_since

<em># Використовуйте f"{user=}", щоб автоматично отримати "user='eric_idle'".</em>
f"{user=} {member_since=}"
<em># Вивід: "user='eric_idle' member_since=datetime.date(1975, 7, 31)"</em>

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

<em># = показує назву змінної, : починає форматування, ,d форматує як ціле число з роздільником тисяч.</em>
f"{delta.days=:,d}"
<em># Вивід: 'delta.days=17,056'</em>

<em># Показуємо як вхідні дані, так і результат обчислення.</em>
from math import cos, radians
theta = 30
f"{theta=} {cos(radians(theta))=:.3f}"
<em># Вивід: 'theta=30 cos(radians(theta))=0.866'</em>

Друк представлень для налагодження (repr)

Об’єкти в Python мають два рядкових представлення: str() (для зручного для користувача виводу) і repr() (для однозначного, зручного для розробника виводу). За замовчуванням f-рядки використовують str(). Щоб отримати вивід repr(), можна використати прапорець перетворення !r, що є зручним скороченням для ручного виклику repr(). Прапорець !s явно викликає str().

class Data:
    def __repr__(self): return '<Data ...>' <em># Представлення для налагодження</em>
    def __str__(self): return 'рядкове представлення' <em># Представлення для користувача</em>
data = Data()

<em># Поведінка за замовчуванням викликає str(data)</em>
f"дані: {data}"
<em># Вивід: 'дані: рядкове представлення'</em>

<em># Використання прапорця !r викликає repr(data)</em>
f"дані: {data!r}"
<em># Вивід: 'дані: <Data ...>'</em>

Доповнення, вирівнювання та обрізання

F-рядки надають повний контроль над форматуванням виводу, включаючи ширину поля, вирівнювання та символи заповнення. Специфікатор формату йде після двокрапки (:).

  • > вирівнює текст по правому краю.
  • < вирівнює текст по лівому краю.
  • ^ центрує текст.
  • Число після символу вирівнювання вказує загальну ширину поля.
  • Символ перед символом вирівнювання вказує символ заповнення.
val = "test"

<em># Вирівняти по правому краю в полі шириною 10 символів</em>
f"{val:>10}"
<em># Вивід: '      test'</em>

<em># Вирівняти по лівому краю і заповнити порожній простір символом '_'</em>
f"{val:_<10}"
<em># Вивід: 'test______'</em>

<em># Центрувати текст</em>
f"{val:^10}"
<em># Вивід: '   test   '</em>

Щоб обрізати рядок до максимальної довжини, використовуйте синтаксис :.N, де N — кількість символів.

instrument = "xylophone"
<em># Обрізати рядок до 5 символів.</em>
f"{instrument:.5}"
<em># Вивід: 'xylop'</em>

Представлення чисел

Для чисел доступно безліч опцій форматування. Ви можете легко перетворювати числа в двійкову (b), вісімкову (o) або шістнадцяткову (x/X) системи. Використання # додає відповідний префікс (0b, 0o, 0x).

answer = 42

<em># Шістнадцяткове представлення</em>
f"{answer:x}, {answer:X}"
<em># Вивід: '2a, 2A'</em>

<em># З префіксом</em>
f"{answer:#x}"
<em># Вивід: '0x2a'</em>

<em># Наукова нотація</em>
f"{answer ** 8:e}"
<em># Вивід: '9.682652e+12'</em>

Доповнення чисел провідними нулями здійснюється за допомогою 0 як символу заповнення. Для чисел з плаваючою комою можна контролювати як загальну ширину, так і кількість знаків після коми. Ви також можете керувати відображенням знака і додавати роздільники тисяч.

<em># Доповнити до 4 цифр провідними нулями</em>
f"{answer:04d}"
<em># Вивід: '0042'</em>

<em># Для Пі: загальна ширина 6, 2 знаки після коми, доповнити нулями</em>
import math
f"{math.pi:06.2f}"
<em># Вивід: '003.14'</em>

<em># Завжди показувати знак (+ для додатних, - для від'ємних)</em>
f"{answer:+d}"
<em># Вивід: '+42'</em>

<em># Використовувати кому як роздільник тисяч</em>
num = 1234567890
f"{num:,d}"
<em># Вивід: '1,234,567,890'</em>

Додаткові теми та найкращі практики

Багато вбудованих об’єктів, як-от datetime, мають власну міні-мову форматування, яка працює безпосередньо в f-рядках.

from datetime import datetime
dt = datetime(2022, 4, 11, 13, 37)
<em># Використовуємо стандартні коди форматування дати/часу</em>
f"{dt:%Y-%m-%d %H:%M}"
<em># Вивід: '2022-04-11 13:37'</em>

Самі специфікатори формату не обов’язково мають бути статичними! Їх можна задавати динамічно за допомогою змінних із вкладеними фігурними дужками.

<em># Ширина та вирівнювання задаються змінними</em>
value = "test"
align = "^"
width = 10
<em># f'{value:{align}{width}}' спочатку перетворюється на f'{value:^10}'</em>
f'{value:{align}{width}}'
<em># Вивід: '   test   '</em>

Якщо вам потрібно включити в рядок літеральну фігурну дужку { або }, просто подвойте її.

f"Літеральні фігурні дужки: {{value}}"
<em># Вивід: 'Літеральні фігурні дужки: {value}'</em>

Практичні поради та підводні камені

Читабельність проти стислості

F-рядки дозволяють вбудовувати дуже складні вирази, але це не завжди гарна ідея. Основний принцип Python — читабельність коду.

Погана практика (важко читати):

<em># Технічно це працює, але що тут відбувається?</em>
print(f"Результат: {round([user.height for user in users if user.active][0] / 2.54, 2)} дюймів.")

Хороша практика (розділення логіки та представлення):

<em># 1. Спочатку готуємо дані</em>
active_users_heights = [user.height for user in users if user.active]
first_user_height_cm = active_users_heights[0]
height_in_inches = round(first_user_height_cm / 2.54, 2)

<em># 2. Потім форматуємо результат</em>
print(f"Результат: {height_in_inches} дюймів.")

Код став довшим, але тепер він зрозумілий, його можна тестувати і легко модифікувати. Загальне правило: якщо вираз всередині {} довший за 20-30 символів або містить складну логіку, краще винести його в окрему змінну.

Багаторядкові f-рядки

Для довгих рядків або генерації багаторядкового тексту (наприклад, SQL-запитів, HTML-шаблонів) використовуйте потрійні лапки. Вирази всередині також можуть бути багаторядковими.

user = "hypo69"
permissions = ['read', 'write', 'execute']

<em># Вираз всередині f-рядка розбитий на кілька рядків для читабельності</em>
report = f"""
Звіт для користувача: {user.upper()}
----------------------------------
Дозволи: {', '.join(p for p in permissions
                            if p != 'execute')}
"""
print(report)

Питання безпеки (Дуже важливо!)

Самі по собі f-рядки є безпечними. Вираз на кшталт f"Привіт, {name}" не є вразливістю; Python просто бере рядкове представлення name.

Небезпека виникає, коли ви комбінуєте f-рядки з функціями, що виконують код, наприклад eval().

ВКРАЙ НЕБЕЗПЕЧНИЙ КОД — НІКОЛИ ТАК НЕ РОБІТЬ:

import os
user_template = input("Введіть шаблон: ") <em># Користувач вводить: '{os.system("reboot")}'</em>
eval(f'f"{user_template}"')

Якщо користувач введе {os.system("reboot")}, ваш сервер перезавантажиться. Це вразливість віддаленого виконання коду (RCE). Ніколи не передавайте рядки, отримані від користувача, у функції на кшталт eval(), навіть через f-рядки. Для шаблонів, визначених користувачем, використовуйте безпечні рушії шаблонів, наприклад Jinja2.

Продуктивність: чому f-рядки такі швидкі?

F-рядок — це не виклик функції, а частина синтаксису Python. Компілятор аналізує f-рядок і розбиває його на літеральні частини та вирази для обчислення. Це компілюється у високоефективний байт-код, який будує кінцевий рядок за одну швидку операцію. Це значно швидше, ніж метод .format(), який повинен аналізувати рядок формату під час виконання.

Інструменти для міграції

Інструменти на кшталт flynt та pyupgrade можуть автоматично перетворювати старий код, що використовує .format() та %, на сучасні f-рядки, що є чудовим способом швидко модернізувати застарілу кодову базу.

Позначки:

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *