Telerik blogs

How do JavaScript template literals compare to Python string formatting? Let’s take a look!

I am super excited to be learning Python. It feels pretty natural to compare Python to the languages I am familiar with (JavaScript and TypeScript) and notice the similarities and differences in their syntax and features.


Image credit: @Dakari_Jaxtyn

In this two-part article series, we will look at string formatting in Python and compare it with template literals in JavaScript. String formatting refers to the ability to substitute parts of a string with values contained in variables or expressions.

Strings in Python

Before talking about string formatting, it is worth highlighting a few things about strings in general in Python. Please feel free to skip this section if you’re already familiar with strings in Python.

We can create strings literals in a few different ways. We can use:

  1. Single quotes
name = 'Monty'
  1. Double quotes
name = "Python"
  1. Triple quotes
trivia = """
Question: Which BBC commedy series is the Python language named after?

Answer: Monty Python's Flying Circus.
"""

We use triple quotes to create multiline strings and also to create docstrings.

  1. The str() method

We use str() to get a string representation of an object.

>>> 'Hello, Number ' + str(5)
'Hello, Number 5'

Unlike JavaScript, we cannot concatenate an integer to a string in Python, otherwise we’ll get a TypeError: can only concatenate str (not “int”) to str.

  1. The repr() method

Similar to str(), we use repr() to get a string representation of an object. Typically, the repr() returns a string that can be executed and yield the same value as the object. This means that a string will be put in quotes.

>>> print(f"Hello, {repr('Monty')} Python!")
Hello, 'Monty' Python!

Strings, like all other variables, are objects in Python. The string variables we created above are objects of class str.

print(type('Hi')). # <class 'str'>

The str class has lots of useful methods, even more than JavaScript.

Formatting Strings Using the % Syntax

%” is the original syntax for formatting strings in Python. We use %s as the placeholder for a variable in the string literal and provide the variable after the string using % variable_name.

In our simple code example below we ask the user to enter a flavor and store their input in a variable. We then display that variable as part of a string.

milkshake_flavours = ['strawberry', 'tropical fruit', 'chocolate', 'bubblegum']
order = input('Please choose a flavour: ')
 
print('Here is you %s milkshake. Enjoy!' % order)

# If we input strawberry it will print:
# Here is you strawberry milkshake. Enjoy!

The code looks pretty neat with just one variable. What if we wanted to allow our customers to choose different flavors to create their own ice cream sundaes? We’d need more variables, one for each selection.

That is fine—we can include multiple %s as placeholders in the string and provide the variables in a parentheses after the % sign.

This is illustrated the following code:

icecream_selection = ['strawberry', 'vanilla', 'chocolate']
jelly_selection = ['lime', 'orange', 'strawberry', 'raspberry', 'blackcurrant']
fruit_selection = ['peaches', 'raspberries', 'blueberries', 'blackberries', 'bananas', 'crushed pineapple', 'mixed fruits']
nut_selection = ['hazelnut', 'peanut', 'pistachio']
sauce_selection = ['chocolate', 'strawberry', 'caramel', 'hot fudge', 'butterscotch']
topping_selection = ['marachino cherry', 'sprinkles', 'marshmallows']

print("""Create your sundae.
Please enter your selections for:""")

icecream =  input('Icecream: ')
fruit = input('Fruits: ')
jelly = input('Jelly: ')
sauce = input('Sauce: ')
nuts = input('Nuts: ')
topping = input('Toppings: ')

print("""
Here's your sundae:

%s icecream with: 
%s, 
%s jelly, 
%s sauce, 
%s, 
and %s on top. 

Enjoy!
""" % (icecream, fruit, jelly, sauce, nuts, topping))

However, displaying quite a few variables in our string has made it more difficult to read and maintain. In addition, we need to make sure the variables are provided in the correct order to match their corresponding %s in the string. With so many variables, it is a more tedious and error-prone task.

Formatting Strings Using the str.format() Method

The string.format() was introduced in Python 2.6 as an improvement on the %s syntax. We use {} as placeholders in our string literal, then call the format() method passing in expressions. The format() method returns a formatted version of the string substituting the placeholders with the values of its arguments.

For example:

print("""
Here is your sundae:
	{} icecream with 
	{}, 
	{} jelly, 
	{} sauce, 
	{}, and
	{} on top
""".format(icecream, fruit, jelly, sauce, nuts, topping))

We can also reference the variables by their index. This allows us to display the variables in a different order than what they were passed in. Note, in the above code when we didn’t provide the index, the default is {0}, {1}, {2}, {3}, {4}, {5}.

print("""
Here is your sundae:
	{0} icecream with 
	{4}, 
	{2} jelly, 
	{3} sauce, 
	{1},
	topped with cream and {5}.
""".format(icecream, nuts, jelly, sauce, fruit, topping))

Even if specifying indexes allows us to use the arguments in a different order to what they were passed in, if we have quite a few arguments the string is harder to read.

We can solve this problem by passing in named keyword arguments instead.

print("""
Here is your sundae:
	{icecream} icecream with 
	{fruit}, 
	{jelly} jelly, 
	{sauce} sauce, 
	{nuts},
	with cream and {topping} on top.
""".format(icecream=icecream, nuts=nuts, fruit=fruit, jelly=jelly, sauce=sauce,  topping=topping))

We can make above code even more readable by putting our options in a dictionary and then using ** syntax to destructure (unpack) the key-value pairs from the dictionary into keyword arguments. The code below illustrates this:

order = {
	'icecream': icecream,
	'topping': topping,
	'sauce': sauce,
	'fruit': fruit,
	'jelly': jelly,
	'nuts': nuts,
}

print("""
Here is your sundae:
	{icecream} icecream with 
	{fruit}, 
	{jelly} jelly, 
	{sauce} sauce, 
	{nuts},
	cream, and 
	{topping} on top.
""".format(**order))

So format(**order) becomes format(icecream=icecream, topping=topping, sauce=sauce, fruit=fruit, jelly=jelly, nuts=nuts).

If you find it tricky to see why this works, remember that we pass in expressions to the format() method. For example:

>>> my_string = '{} * {} = {}'.format(3, 6, 3 * 6)
>>> my_string
'3 * 6 = 18'

The format() method is definitely an improvement on the %s syntax for formatting strings. However, it is not the latest or the best. Nonetheless, it is important to know about the format() method as we will likely come across code that uses it. What is the latest way of formatting string in Python then? Let’s find out next.

Formatting Strings Using the Formatted String Literals (f)

The formatted string literals which was introduced in Python 3 is the latest and most straightforward way of formatting strings in Python.

We put the letter f or F in front of a string literal and specify expressions within curly braces {} in the string. Expressions within formatted literals can directly access variables in the namespace. Which means we don’t need to pass in any arguments or worry about matching placeholders with arguments anymore. As a result, our code is more concise, easier to read and easier to maintain. Yay! Formatted string literals are similar to template literals in JavaScript.

print(f"""
icecream =  input('Icecream: ')
fruit = input('Fruits: ')
jelly = input('Jelly: ')
sauce = input('Sauce: ')
nuts = input('Nuts: ')
topping = input('Toppings: ')

Here is your sundae:
	{icecream} icecream with 
	{fruit}, 
	{jelly} jelly, 
	{sauce} sauce, 
	{nuts},
	cream, and 
	{topping} on top.
""")

Of course, if we used a variable name in an expression that is not in the namespace, we will get an error.

Also note, we can use formatted string literals with:

  • Single quotes f'expression',
  • Double quotes f"{expression}", or
  • Tripple quotes f"""{expression}"""

But that is not all! On top of string interpolation, we can format values within the string literals using Python’s format specification mini-language. Let’s look at that next.

Format Specification Mini-Language

We can optionally specify type conversion and format_spec options in a formatted string or a string with the format() method.

Example:

>>> price = 0.30
>>> price
0.3

>>> f'{price:.2f}'
'0.30'

>>> '{:.2f}'.format(price)
'0.30'

An exclamation mark denotes a conversion and a colon denotes a format_spec option.

f'{expression!conversion:format_spec}'

Type conversion is done before formatting the string. !s applies the str(value) method to a value, while !r applies the repr(value) method.

For example, if we wanted to format a string in quotes, we would use the !r modifier. In the code below, we have defined the __str__() method. This lets us print details of a class instance in a more readable way. We have used !r in a formatted string literal to put quotes around the text “fresh cream.”

class Sundae:
	def __init__(self, icecream, sauce, topping):
		self.icecream = icecream
		self.sauce = sauce
		self.topping = topping

	def __str__(self):
		return f'{self.icecream.capitalize()} icecream with {'fresh cream'!r}, {self.sauce} sauce and {self.topping} on top.'

order1 = Sundae('strawberry', 'chocolate', 'cherries')
print(f'{order1}')

# prints:
"Strawberry icecream with 'fresh cream', chocolate sauce and cherries on top."

The format_spec options include:

f'{expression:[[fill]align][sign][#][0][width][grouping_option][.precision][type]}'

The code example below illustrates using fill, align, width, precision and type format_spec options.

width = 50
price_list = [
	{'item': 'Milkshake', 'price': 5.70}, 
	{'item': 'Wafles and Cookie Dough', 'price': 5.50}, 
	{'item': 'Create your Own', 'price': 9.95}, 
	{'item': 'Waffle Pop', 'price': 4.00}
]

price_message = f"""
{'-':-^{width}}
{'Mayas Treats':^{width}}
{'-':-^{width}}

Price List:

"""

for product in price_list:
	price_message += f"\n{product['item']:.<45}£{product['price']:.2f}"

Prints:

--------------------------------------------------
                   Mayas Treats                   
--------------------------------------------------

Price List:
Milkshake....................................£5.70
Wafles and Cookie Dough......................£5.50
Create your Own..............................£9.95
Waffle Pop...................................£4.00

Here is an explanation of the mini-language used in the code above:

  • f'{'-':-^{width}}' – says center the text “-” within the specified width (50) and fill in the space with the given text (also “-”). The result is 50 dashes (dashes taking up 50 characters).

  • f'{'Mayas Treats':^{width}}' – centers “Mayas Treats” within a width of 50. Since I didn’t specify a fill character, we get the default space.

  • f'{product['price']:.2f}' – displays price as a float with precision of 2 digits after the decimal. The default precision is 6 digits.

Please refer to Python Docs to learn more.

Hope this article has been helpful or inspiring in some way.

 


ashnita-bali
About the Author

Ashnita Bali

Ashnita is a frontend web developer who loves JavaScript and Angular. She is an organizer at GDGReading, a WomenTechmakers Ambassador and a mentor at freeCodeCampReading. Ashnita is passionate about learning and thinks that writing and sharing ideas are great ways of learning. Besides coding, she loves the outdoors and nature.

Related Posts

Comments

Comments are disabled in preview mode.