Форматування рядків за допомогою f-рядків¶
Python 3.6 додав новий варіант форматування рядків - f-рядки або інтерполяція рядків.
F-рядки дозволяють не тільки підставляти якісь значення шаблону, але й дозволяють здійснювати виклики функцій, методів тощо.
У багатьох ситуаціях f-рядки зручніше і простіше використовувати, ніж format.
Синтаксис¶
F-рядки – це літерал рядка з літерою f перед ним. Усередині f-рядка в парі фігурних дужок вказуються імена змінних, які треба підставити:
In [1]: ip = '10.1.1.1'
In [2]: mask = 24
In [3]: f"IP: {ip}, mask: {mask}"
Out[3]: 'IP: 10.1.1.1, mask: 24'
Аналогічний результат format можна отримати так:
Дуже важлива відмінність f-рядків від format: f-рядки це вираз, який
виконується, а не просто рядок. Тобто, у випадку з ipython, як тільки ми
написали вираз і натиснули Enter, вираз виконався і замість виразів {ip}
та
{mask}
підставилися значення змінних.
Тому, наприклад, не можна спочатку написати шаблон, а потім визначити змінні, які використовуються у шаблоні:
In [1]: f"IP: {ip}, mask: {mask}"
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-e6f8e01ac9c4> in <module>()
----> 1 f"IP: {ip}, mask: {mask}"
NameError: name 'ip' is not defined
Крім підстановки значень змінних, у фігурних дужках можна писати вирази:
In [1]: octets = ['10', '1', '1', '1']
In [2]: mask = 24
In [3]: f"IP: {'.'.join(octets)}, mask: {mask}"
Out[3]: 'IP: 10.1.1.1, mask: 24'
Після двокрапки у f-рядках можна вказувати ті ж значення, що і при використанні format:
oct1, oct2, oct3, oct4 = [10, 1, 1, 1]
print(f'''
IP address:
{oct1:<8} {oct2:<8} {oct3:<8} {oct4:<8}
{oct1:08b} {oct2:08b} {oct3:08b} {oct4:08b}''')
Результат
Особливості використання f-рядків¶
При використанні f-рядків не можна спочатку створити шаблон, а потім його використовувати як при використанні format. F-рядок відразу виконується і до нього підставляються значення змінних, які мають бути визначені раніше:
Якщо необхідно підставити інші значення, треба створити нові змінні (з тими самими іменами) і знову написати f-рядок:
При використанні f-рядків у циклах, f-рядок треба писати в тілі циклу, щоб він "підхоплював" нові значення змінних на кожній ітерації:
In [1]: ip_list = ['10.1.1.1/24', '10.2.2.2/24', '10.3.3.3/24']
In [2]: for ip_address in ip_list:
...: ip, mask = ip_address.split('/')
...: print(f"IP: {ip}, mask: {mask}")
...:
IP: 10.1.1.1, mask: 24
IP: 10.2.2.2, mask: 24
IP: 10.3.3.3, mask: 24
Приклади використання f-рядків¶
Базова підстановка змінних:
In [1]: intf_type = 'Gi'
In [2]: intf_name = '0/3'
In [3]: f'interface {intf_type}/{intf_name}'
Out[3]: 'interface Gi0/3'
Вирівнювання стовпцями:
topology = [['sw1', 'Gi0/1', 'r1', 'Gi0/2'],
['sw1', 'Gi0/2', 'r2', 'Gi0/1'],
['sw1', 'Gi0/3', 'r3', 'Gi0/0'],
['sw1', 'Gi0/5', 'sw4', 'Gi0/2']]
In [7]: for connection in topology:
...: l_device, l_port, r_device, r_port = connection
...: print(f'{l_device:10} {l_port:7} {r_device:10} {r_port:7}')
...:
sw1 Gi0/1 r1 Gi0/2
sw1 Gi0/2 r2 Gi0/1
sw1 Gi0/3 r3 Gi0/0
sw1 Gi0/5 sw4 Gi0/2
Ширина стовпців може бути вказана через змінну:
topology = [['sw1', 'Gi0/1', 'r1', 'Gi0/2'],
['sw1', 'Gi0/2', 'r2', 'Gi0/1'],
['sw1', 'Gi0/3', 'r3', 'Gi0/0'],
['sw1', 'Gi0/5', 'sw4', 'Gi0/2']]
width = 10
In [8]: for connection in topology:
...: l_device, l_port, r_device, r_port = connection
...: print(f'{l_device:{width}} {l_port:{width}} {r_device:{width}} {r_port:{width}}')
...:
sw1 Gi0/1 r1 Gi0/2
sw1 Gi0/2 r2 Gi0/1
sw1 Gi0/3 r3 Gi0/0
sw1 Gi0/5 sw4 Gi0/2
Робота зі словниками
session_stats = {'done': 10, 'todo': 5}
In [2]: if session_stats['todo']:
...: print(f"Pomodoros done: {session_stats['done']}, TODO: {session_stats['todo']}")
...: else:
...: print(f"Good job! All {session_stats['done']} pomodoros done!")
...:
Pomodoros done: 10, TODO: 5
Виклик функції len усередині f-рядка:
topology = [['sw1', 'Gi0/1', 'r1', 'Gi0/2'],
['sw1', 'Gi0/2', 'r2', 'Gi0/1'],
['sw1', 'Gi0/3', 'r3', 'Gi0/0'],
['sw1', 'Gi0/5', 'sw4', 'Gi0/2']]
In [3]: print(f'Кількість підключень в топології: {len(topology)}')
Кількість підключень в топології: 4
Виклик методу upper всередині f-рядка:
Конвертація чисел у двійковий формат:
In [7]: ip = '10.1.1.1'
In [8]: oct1, oct2, oct3, oct4 = ip.split('.')
In [9]: print(f'{int(oct1):08b} {int(oct2):08b} {int(oct3):08b} {int(oct4):08b}')
00001010 00000001 00000001 00000001
Що використовувати format або f-рядки¶
У багатьох випадках f-рядки зручніше використовувати, оскільки шаблон виглядає зрозумілішим і компактнішим. Однак бувають випадки, коли метод format зручніший. Наприклад:
In [6]: ip = [10, 1, 1, 1]
In [7]: oct1, oct2, oct3, oct4 = ip
...: print(f'{oct1:08b} {oct2:08b} {oct3:08b} {oct4:08b}')
...:
00001010 00000001 00000001 00000001
In [8]: template = "{:08b} "*4
In [9]: template.format(oct1, oct2, oct3, oct4)
Out[9]: '00001010 00000001 00000001 00000001 '
Ще одна ситуація, коли format, як правило, зручніше використовувати: необхідність використовувати в скрипті той самий шаблон багато разів. F-рядок виконається перший раз і підставить поточні значення змінних та для використання шаблону ще раз, його треба заново писати. Це означає, що в скрипті будуть копії одного і того ж рядка. У той же час, format дозволяє створити шаблон в одному місці і потім використовувати його повторно, підставляючи змінні при необхідності.
Це можна обійти, створивши функцію, але створювати функцію для виведення рядка за шаблоном далеко не завжди виправдано. Приклад створення функції: