-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPython String Formatting 1
More file actions
475 lines (361 loc) · 23.9 KB
/
Copy pathPython String Formatting 1
File metadata and controls
475 lines (361 loc) · 23.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
Interpolating and Formatting Strings in Python
Using F-Strings to Format Strings
Using the Formatting Mini-Language With F-Strings
Formatting Strings With F-Strings: A Practical Example
Using str.format() to Format Strings
Using the Formatting Mini-Language With .format()
Formatting Strings With .format(): Practical Examples
Formatting Strings With the Modulo Operator (%)
Using Conversion Specifiers
Using Conversion Flags
Deciding Which String Formatting Tool to Use
Conclusion
Frequently Asked Questions
Remove ads
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Python String Formatting Tips & Best Practices
String formatting is essential in Python for creating dynamic and well-structured text by inserting values into strings. This tutorial covers various methods, including f-strings, the .format() method, and the modulo operator (%). Each method has unique features and benefits for different use cases. The string formatting mini-language provides additional control over the output format, allowing for aligned text, numeric formatting, and more.
By the end of this tutorial, you’ll understand that:
String formatting in Python involves inserting and formatting values within strings using interpolation.
Python supports different types of string formatting, including f-strings, the .format() method, and the modulo operator (%).
F-strings are generally the most readable and efficient option for eager interpolation in Python.
Python’s string formatting mini-language offers features like alignment, type conversion, and numeric formatting.
While f-strings are more readable and efficient compared to .format() and the % operator, the .format() method supports lazy evaluation.
To get the most out of this tutorial, you should be familiar with Python’s string data type and the available string interpolation tools. Having a basic knowledge of the string formatting mini-language is also a plus.
Get Your Code: Click here to download the free sample code you’ll use to learn about Python’s string formatting tools.
Take the Quiz: Test your knowledge with our interactive “Python String Formatting: Available Tools and Their Features” quiz. You’ll receive a score upon completion to help you track your learning progress:
Python String Formatting: Available Tools and Their Features
Interactive Quiz
Python String Formatting: Available Tools and Their Features
You can take this quiz to test your understanding of the available tools for string formatting in Python, as well as their strengths and weaknesses. These tools include f-strings, the .format() method, and the modulo operator.
Interpolating and Formatting Strings in Python
String interpolation involves generating strings by inserting other strings or objects into specific places in a base string or template. For example, here’s how you can do some string interpolation using an f-string:
>>> name = "Bob"
>>> f"Hello, {name}!"
'Hello, Bob!'
In this quick example, you first have a Python variable containing a string object, "Bob". Then, you create a new string using an f-string. In this string, you insert the content of your name variable using a replacement field. When you run this last line of code, Python builds a final string, 'Hello, Bob!'. The insertion of name into the f-string is an interpolation.
Note: To dive deeper into string interpolation, check out the String Interpolation in Python: Exploring Available Tools tutorial.
When you do string interpolation, you may need to format the interpolated values to produce a well-formatted final string. To do this, you can use different string interpolation tools that support string formatting. In Python, you have these three tools:
F-strings
The str.format() method
The modulo operator (%)
The first two tools support the string formatting mini-language, a feature that allows you to fine-tune your strings. The third tool is a bit old and has fewer formatting options. However, you can use it to do some minimal formatting.
Note: The built-in format() function is yet another tool that supports the format specification mini-language. This function is typically used for date and number formatting, but you won’t cover it in this tutorial.
In the following sections, you’ll start by learning a bit about the string formatting mini-language. Then, you’ll dive into using this language, f-strings, and the .format() method to format your strings. Finally, you’ll learn about the formatting capabilities of the modulo operator.
Remove ads
Using F-Strings to Format Strings
Python 3.6 added a string interpolation and formatting tool called formatted string literals, or f-strings for short. As you’ve already learned, f-strings let you embed Python objects and expressions inside your strings. To create an f-string, you must prefix the string with an f or F and insert replacement fields in the string literal. Each replacement field must contain a variable, object, or expression:
>>> f"The number is {42}"
'The number is 42'
>>> a = 5
>>> b = 10
>>> f"{a} plus {b} is {a + b}"
'5 plus 10 is 15'
In the first example, you define an f-string that embeds the number 42 directly into the resulting string. In the second example, you insert two variables and an expression into the string.
Formatted string literals are a Python parser feature that converts f-strings into a series of string constants and expressions. These are then joined up to build the final string.
Using the Formatting Mini-Language With F-Strings
When you use f-strings to create strings through interpolation, you need to use replacement fields. In f-strings, you can define a replacement field using curly brackets ({}) as in the examples below:
>>> debit = 300.00
>>> credit = 450.00
>>> f"Debit: ${debit}, Credit: ${credit}, Balance: ${credit - debit}"
'Debit: $300, Credit: $450.0, Balance: $150.0'
Inside the brackets, you can insert Python objects and expressions. In this example, you’d like the resulting string to display the currency values using a proper format. However, you get a string that shows the currency values with at most one digit on its decimal part.
To format the values and always display two digits on its decimal part, you can use a format specifier:
>>> f"Debit: ${debit:.2f}, Credit: ${credit:.2f}, Balance: ${credit - debit:.2f}"
'Debit: $300.00, Credit: $450.00, Balance: $150.00'
In this example, note that each replacement field contains a string that starts with a colon. That’s a format specifier. The .2f part tells Python that you want to format the value as a floating-point number (f) with two decimal places (.2).
Note: To learn more about the formatting mini-language and its syntax, check out the Python’s Format Mini-Language for Tidy Strings tutorial. If you’re interested in formatting floating-point numbers specifically, then you can also read How to Format Floats Within F-Strings in Python.
The string formatting mini-language is a powerful tool with several cool features, including the following:
Strings alignment
Conversion between input objects’ types
Numeric values formatting
Dynamic formatting
In the following sections, you’ll explore how to use f-strings, the .format() method, and the string formatting mini-language to format the values that you insert into your strings through interpolation.
Formatting Strings With F-Strings: A Practical Example
You can use f-strings and the string formatting mini-language to format the values that you interpolate into your strings in multiple ways. To illustrate, say that you want to write a Python function to build a grades report for your students. The student data is in a dictionary that looks like the following:
>>> student = {
... "name": "John Doe",
... "subjects": [
... {
... "name": "Mathematics",
... "grade": 88,
... "comment": "Excellent improvement.",
... },
... {
... "name": "Science",
... "grade": 92,
... "comment": "Outstanding performance.",
... },
... {
... "name": "History",
... "grade": 78,
... "comment": "Needs to participate more.",
... },
... {
... "name": "Art",
... "grade": 85,
... "comment": "Very creative."
... },
... ],
... }
The dictionary has the name key to store the student’s name. Then, it has the subjects key to hold a list of dictionaries containing the student’s performance in each subject.
Your function may look like the following:
grades_report_v1.py
def build_student_report(student):
report_header = f"Progress Report. Student: {student['name']}"
total = sum(subject["grade"] for subject in student["subjects"])
average = total / len(student["subjects"])
average_report = f"Average: {average:.2f} / 100\n"
subject_report = "Course Details:\n"
for subject in student["subjects"]:
subject_report += (
f"{subject['name']:<15} "
f"Grade: {subject['grade']:3d} "
f"Comment: {subject['comment']}\n"
)
return f"""
{report_header}
{average_report}
{subject_report}
Thank you for reviewing the progress report.
"""
In this function, you’re doing several things. Here’s a line-by-line breakdown:
Line 2 defines a heading for the report.
Line 4 sums all the grades.
Line 5 computes the average of the grades.
Line 6 defines the average grade subreport. In this part of the report, you use the .2f format specifier to express the average grade as a floating-point number with two decimal places.
Line 8 defines the first line of the subject subreport.
Line 9 starts a loop over the subjects.
Line 10 adds more information to the subject subreport.
Line 11 formats the subject’s name. To do this, you use the <15 format specifier, which tells Python to align the name to the left within 15 characters.
Line 12 formats the grade. In this case, the 3d format specifier tells Python to display the grade using up to three characters. A leading space is used if the grade doesn’t have three digits.
Line 13 adds the comment part.
Lines 16 to 21 build the final report and return it to the caller.
Now that you’ve gone through the complete code, it’s time to try out your function. Go ahead and run the following code:
>>> from grades_report_v1 import build_student_report
>>> print(build_student_report(student))
Progress Report. Student: John Doe
Average: 85.75 / 100
Course Details:
Mathematics Grade: 88 Comment: Excellent improvement.
Science Grade: 92 Comment: Outstanding performance.
History Grade: 78 Comment: Needs to participate more.
Art Grade: 85 Comment: Very creative.
Thank you for reviewing the progress report.
Your report looks pretty nice! It provides general information about the student at the top and grade details for every subject.
Remove ads
Using str.format() to Format Strings
You can also use the .format() method to format values during string interpolation. In most cases, you’d use the .format() method for lazy interpolation. In this type of interpolation, you define a template string in some part of your code and then interpolate values in another part:
>>> number_template = "The number is {}"
>>> sum_template = "{0} plus {1} is {2}"
>>> number_template.format(42)
'The number is 42'
>>> a = 5
>>> b = 10
>>> sum_template.format(a, b, a + b)
'5 plus 10 is 15'
In both examples, you create a string template and then use the .format() method to interpolate the required values.
Using the Formatting Mini-Language With .format()
The str.format() method also supports the string formatting mini-language. This feature allows you to nicely format the interpolated values when you create strings through interpolation. To illustrate, consider the example you wrote in the section about using the formatting mini-language with f-strings.
Here’s how to do it with the .format() method:
>>> debit = 300.00
>>> credit = 450.00
>>> template = "Debit: ${0:.2f}, Credit: ${1:.2f}, Balance: ${2:.2f}"
>>> template.format(debit, credit, credit - debit)
'Debit: $300.00, Credit: $450.00, Balance: $150.00'
Again, the resulting string displays the currency values using a proper format that shows two decimal places.
Formatting Strings With .format(): Practical Examples
Now it’s time for a couple of practical examples of using the .format() method and the string formatting mini-language to format your strings.
For the first example, say that you need to create a sales report for your company. You’d like to create a report template and fill it with the appropriate data when someone requires it. In this situation, you can create the following report template:
sales_report.py
REPORT_TEMPLATE = """
Monthly Sales Report
--------------------
Report Date Range: {start_date} to {end_date}
Number of Transactions: {sep:.>20} {transactions:,}
Average Transaction Value: {sep:.>11} ${avg_transaction:,.2f}
Total Sales: {sep:.>23} ${total_sales:,.2f}
"""
In this report template, you have a few format specifiers. Here’s a summary of their specific meanings:
.>20 displays the interpolated value aligned to the right within a space of 20 characters. The dot after the colon works as the fill character. The other format specifiers, .>11 and .>23, have a similar effect. Note that the field widths were chosen by trial and error to make the report line up nicely.
, displays the preceding number using a comma as the thousands separator.
,.2f shows a value as a floating-point number using two decimal places and a comma as the thousands separator.
Now, you can code a function to generate the actual report:
sales_report.py
# ...
def build_sales_report(sales_data, report_template=REPORT_TEMPLATE):
total_sales = sum(sale["amount"] for sale in sales_data)
transactions = len(sales_data)
avg_transaction = total_sales / transactions
return report_template.format(
sep=".",
start_date=sales_data[0]["date"],
end_date=sales_data[-1]["date"],
total_sales=total_sales,
transactions=transactions,
avg_transaction=avg_transaction,
)
This function takes the sales data and the report template as arguments. Then, it computes the required values and calls .format() on the template. Go ahead and give this function a try by running the following code:
>>> from sales_report import build_sales_report
>>> sales_data = [
... {"date": "2024-04-01", "amount": 100},
... {"date": "2024-04-02", "amount": 200},
... {"date": "2024-04-03", "amount": 300},
... {"date": "2024-04-04", "amount": 400},
... {"date": "2024-04-05", "amount": 500},
... ]
>>> print(build_sales_report(sales_data))
Monthly Sales Report
--------------------
Report Date Range: 2024-04-01 to 2024-04-05
Number of Transactions: .................... 5
Average Transaction Value: ........... $300.00
Total Sales: ....................... $1,500.00
Cool! You have a nicely formatted sales report. You can experiment on your own and tweak the format specifiers further as an exercise. For example, you can improve the date format. However, note that dates have their own formatting, which you can learn about in the Formatting Dates section of the tutorial about Python’s string formatting mini-language.
You can also take advantage of the .format() method when your data is stored in dictionaries. For example, here’s how you can update the build_student_report() function using the .format() method:
grades_report_v2.py
SUBJECT_TEMPLATE = "{name:<15} Grade: {grade:3} Comment: {comment}"
REPORT_TEMPLATE = """
Progress Report. Student: {name}
Average: {average:.2f} / 100
Course Details:
{subjects_report}
Thank you for reviewing the progress report.
"""
def build_student_report(student):
data = {
"name": student["name"],
"average": sum(subject["grade"] for subject in student["subjects"])
/ len(student["subjects"]),
"subjects_report": "\n".join(
SUBJECT_TEMPLATE.format(**subject)
for subject in student["subjects"]
),
}
return REPORT_TEMPLATE.format(**data)
In the first lines of code, you create string templates to display the information about each subject and also the final report. In build_student_report(), you create a dictionary with the required data to build the student report. Next, you interpolate the data into the report template using .format() with the dictionary as an argument.
Note that to fill the string templates, you use the ** operator to unpack the data from the input dictionary.
Remove ads
Formatting Strings With the Modulo Operator (%)
Strings in Python have a built-in operation that you can access with the modulo operator (%). This operator lets you do positional and named string interpolation. If you’ve ever worked with the printf() function in C, then the syntax will be familiar. Here’s a toy example:
>>> name = "Bob"
>>> "Hello, %s" % name
'Hello, Bob'
The %s substring is a conversion specifier that works as a replacement field. It tells Python where to substitute the value of name, represented as a string.
Using Conversion Specifiers
To build a conversion specifier, you need two or more characters. Here’s a quick summary of the accepted characters and their corresponding order in the specifier:
The % character marks the start of the specifier.
An optional mapping key in parentheses allows you to use named replacement fields like (name).
An optional conversion flag affects how some conversion types display.
An optional minimum field width allows you to define the number of characters to display.
An optional precision consists of a dot character (.) followed by the desired precision.
An optional length modifier is an l or h for long and short integers.
A conversion type specifies how the output string will be formatted, mimicking different data types.
Several conversion types are available for the modulo operator in Python. They allow you to control the output’s format in some way. For example, you can convert numbers to hexadecimal notation or add whitespace padding to generate nicely formatted tables and reports.
Here’s a summary of the conversion types currently available in Python:
Conversion Type Description
d Signed integer decimal
i Signed integer decimal
o Signed octal value
x Signed hexadecimal with lowercase prefix
X Signed hexadecimal with uppercase prefix
e Floating-point exponential format with lowercase e
E Floating-point exponential format with uppercase E
f Floating-point decimal format
F Floating-point decimal format
g Floating-point format
G Floating-point format
c Single character (accepts integer or single character string)
r String as per calling repr()
s String as per calling str()
a String as per calling ascii()
% A percentage character (%) in the result if no argument is converted
With all these conversion types, you can process your interpolated values to display them using different representation types.
Note: It’s important to note that f-strings and the .format() method also support the conversion types listed above. For details on this topic, check out the Converting Between Type Representations section in the Python’s Format Mini-Language for Tidy Strings tutorial.
Here are a few examples of how to use some of the above specifiers in your strings:
>>> "%d" % 123.123 # As an integer
'123'
>>> "%o" % 42 # As an octal
'52'
>>> "%x" % 42 # As a hex
'2a'
>>> "%e" % 1234567890 # In scientific notation
'1.234568e+09'
>>> "%f" % 42 # As a floating-point number
'42.000000'
In these examples, you’ve used different conversion types to display values using different type representations. Now, check out the examples below to see other formatting options in action:
>>> # Named replacement fields
>>> jane = {"first_name": "Jane", "last_name": "Doe"}
>>> "Full name: %(first_name)s %(last_name)s" % jane
'Full name: Jane Doe'
>>> # Minimal width of 15 chars
>>> "%-15f" % 3.1416 # Aligned to the left
'3.141600 '
>>> "%15f" % 3.1416 # Aligned to the right
' 3.141600'
>>> # Dynamic width
>>> width = 15
>>> "%-*f" % (width, 3.1416)
'3.141600 '
>>> "%*f" % (width, 3.1416)
' 3.141600'
>>> # Precision
>>> "%.2f" % 3.141592653589793
'3.14'
>>> "%.4f" % 3.141592653589793
'3.1416'
>>> "%.8f" % 3.141592653589793
'3.14159265'
In the first example, you use named replacement fields in parentheses and a dictionary to provide the values you want to interpolate. In the second example, you provide a minimum width for your string in characters.
The third example is a dynamic variation of the second. Note how the * symbol allows you to insert the desired width dynamically.
Finally, you use the precision option to display a floating-point number using different precisions. You use two, four, and eight digits after the decimal separator, respectively.
Unfortunately, the modulo operator doesn’t support the string formatting mini-language, so if you use this tool to interpolate and format your strings, then your formatting options are more limited than when you use f-strings or format().
Remove ads
Using Conversion Flags
The modulo operator also supports what’s known as conversion flags. Here’s a quick summary of the currently available flags:
Conversion Flag Description
'#' Displays numeric values using alternate forms
'0' Adds zero padding for numeric values
'-' Left-justifies the value (overrides the '0' conversion if both are given)
' ' (space) Adds a space before a positive number
'+' Adds a sign character ('+' or '-') before the value
These flags help you apply some additional formatting options to your strings. Consider the following quick examples:
>>> "%o" % 10
'12'
>>> "%#o" % 10
'0o12'
>>> "%x" % 31
'1f'
>>> "%#x" % 31
'0x1f'
In these examples, you demonstrate the effect of the # flag, which prepends the appropriate prefix to the input number depending on the base you use. This flag is mostly used with integer values.
Here are some more examples of using different flags:
>>> "%05d" % 42
'00042'
>>> "%10d" % 42
' 42'
>>> "%-10d" % 42
'42 '
>>> "% d" % 42
' 42'
>>> "% d" % -42
'-42'
>>> "%+d" % 42
'+42'
>>> "%+d" % -42
'-42'
In the first example, you add zero padding to the input value. Next, you have an example of how to use the minus sign to align a value to the left in a width of ten characters.
The space flag allows you to add a space before positive numbers. This space disappears when the value is negative. Finally, you use the plus sign so the string always displays whether the input value is positive or negative.
Deciding Which String Formatting Tool to Use
You’ve learned about three different tools for string formatting up to this point. Having several choices for one task can be confusing. In the end, what tool should you use?
If you want readable syntax, good performance, and you’re doing eager interpolation, then f-strings are for you. On the other hand, if you need a tool for doing lazy string interpolation, then the .format() method is the way to go.
In contrast, the modulo operator (%) is an old-fashioned tool not commonly used in modern Python. You could say that this tool is almost dead. However, you may find it in legacy Python code, so it’s good to know how it works.
The following table compares the three tools using several comparison criteria:
Feature F-strings .format() %
Readability High Medium Low
Supports lazy evaluation ⛔️ ✅ ✅
Supports dictionary unpacking ⛔️ ✅ ✅
Supports the format mini-language ✅ ✅ ⛔️
Supports conversion types ✅ ✅ ✅
Supports conversion flags ✅ ✅ ✅
F-strings are the clear winner in terms of readability. However, they don’t allow you to do lazy interpolation. There’s no way to use an f-string to create a reusable string template that you can interpolate later in your code. If you want a universal tool with all the features, then the .format() method is the way to go.
As you’ve learned in this tutorial, Python has several tools that allow you to format your strings during interpolation. In modern Python, you’ll see and use f-strings or the .format() method most of the time. In legacy code, you can see the modulo operator being used.