5. Using Strings and print()#

5.1. Lesson overview#

Being able to communicate effectively is an important skill for an engineer. Technical documents (e.g., reports, manuscripts, books) and presentations relay information that an engineer has observed, calculated, or discovered to an audience in a meaningful way. Notes that an engineer takes during an experiment or when analyzing data helps them remember important details of their work. As such, it is vital that an engineer can relay this information to themselves or to others in a clear and understandable way.

This is no different to having a computer program output information, since we want this information to be easily read by someone. In a previous lesson, we introduced the str data class (i.e., a text-based class) and the print() function to output information to the Python terminal. Our ability to use these two features so far have been limited to simple one line outputs and limited intermixing of data classes. In this lesson, we will explore the str class and the print() function in more detail in order to create more meaningful text-based outputs to the terminal.

5.2. Combining strings#

As we have previously discussed, the str data class focuses on creating “strings” of text-based characters (e.g., letters, words, symbols). Python can combine multiple strings together by using the addition operator (+). To see how this works, imagine we want to create the string Chemical Engineering and Materials Science! and have it displayed in the terminal. There are a few ways to do this, but for this example, let us create five str variables that represent each of the words:

a = "Chemical"
b = "Engineering"
c = "and"
d = "Materials"
e = "Science!"

Now let us combine these five objects into one str variable called cems using the + operator and then display cems using the print() function. The block of code below tries to enact this operation:

cems = a + b + c + d + e
print(cems)
ChemicalEngineeringandMaterialsScience!

OOPS! So close! While we did get the five str objects to combine into each other, we are missing a space character between each word. This is a very common coding error, even for experienced programmers. One quick fix is to reassign each of the first four variables (i.e., a, b, c, and d) with the last character being a space character (e.g., instead of “Chemical” we write “Chemical . See the following cell with this minor but important modification:

a = "Chemical "
b = "Engineering "
c = "and "
d = "Materials "
e = "Science!"

cems = a + b + c + d + e
print(cems)
Chemical Engineering and Materials Science!

Alright! We now got it to display correctly. Notice that the addition operation order matters here. The combined string is created in a left to right fashion. Not following this order can lead to the wrong str being created. If we rearrange the addition order we end up with a nonsensical output:

msce = d + e + c + a + b
print(msce)
Materials Science!and Chemical Engineering 

5.2.1. Example: State your name#

Create three str-based variables that contain your first name, your last name, and the year you were born. Call them first_name, last_name, and year, respectively. Use these three variables to print out the following two strings to the terminal:

first_name, last_name, year

last_name, first_name, year

How do you plan to add the comma and space characters to your print() calls?


Solution:

As demonstrated in the lesson, we use the + operator to combine strings together. The only additional trick in this example is how to add a comma followed by a space character after the first two entries. This is done by including the string ,   between the first and second entries and the second and third entries. Details are shown below:

first_name = "Goldy"
last_name = "Gopher"
year = "1851"

print(first_name + ", " + last_name + ", " + year)
print(last_name + ", " + first_name + ", " + year)
Goldy, Gopher, 1851
Gopher, Goldy, 1851

5.3. Indexing strings#

The str class is actually a sequence data type like list, tuple, and range. You can think of str as a sequence of characters, which means a str is indexable. Therefore, we can call characters from specific indexed positions just like how we did with other sequence classes. To see this in action, let us revisit our variable cems and display the values of some index positions:

print(cems[0])
print(cems[0:20])
print(cems[25:])
C
Chemical Engineering
Materials Science!

In the first example, we call for the first position in cems (i.e., the 0th indexed position), which is the C character in “Chemical”. The second example calls the 0th through 20th position by using the : operator between 0 and 20. Note that this also includes the space between “Chemical” and “Engineering” since the space is also a character. The third example highlights a shortcut when issuing index calls. Here, we see that the 25th indexed position is called for the first position, but nothing is included after the : symbol. The Python shell interprets this as to read to the end of the string. This is why the print() command displays everything starting from M (i.e., the 25th indexed position in cems) to the last character !.

Hey! Listen!

Remember that Python indexes the first position in a sequence as the 0th position.

Overall, indexing strings is very powerful because it allows you to take apart, modify, or recombine a str in different ways.

5.3.1. Example: The first letter counts#

Create a new str object that contains the first letter from each word in the string Chemical Engineering and Materials Science by using string indexing. In this exercise, exclude the word and from the extraction process. Print out this new string to the terminal.


Solution:

There are a few ways in Python to do this, but in this example we use our basic knowledge on how to index a string with the [] operators. There are four words we need to extract the first letter from (see the problem statement about excluding and from the analysis). The characters in question are at the 0, 9, 25, and 35 index position of the starting string, which is called start_str in the example code below. We first create a new string called new_str that stores these characters, and then run the print() function to display the results to the terminal.

start_str = "Chemical Engineering and Materials Science"
new_str = start_str[0] + start_str[9] + start_str[25] + start_str[35]

print(new_str)
CEMS

5.4. The newline character (\n) and other “escape” characters#

It is often useful to separate displayed text (i.e., str objects) using a new output line. For example, imagine we want to display Hey! Listen! in the terminal. We can use the print()function to display this str all in one line:

print("Hey! Listen!")
Hey! Listen!

What if we now want to display Hey! and Listen! on separate lines? One easy way to do this is to replace the space character between Hey! and Listen! with the newline character \n. Try the following cell to see what happens:

print("Hey!\nListen!")
Hey!
Listen!

Another way to achieve our desired output is to run two separate print() functions for each word. We have used this method a few times in previous lessons. The block of code for this method is shown below:

print("Hey!")
print("Listen!")
Hey!
Listen!

This code is a bit more human-readable, and also demonstrates that the print() function is automatically adding a \n at the end of each print() call. We will revisit this observation in the next section.

What if we now want an additional blank line between the Hey! and Listen!? With the \n character this is pretty straightforward as we can issue an additional print() function with just \n as the input:

print("Hey!")
print("\n")
print("Listen!")
Hey!


Listen!

The newline character \n is just that, a character, much like the letter a or the number 1 when issued in a str. The newline character belongs to a group of special characters in Python known as “escape characters” that increase the readability of str objects when they are displayed. For example, what if we wanted to include quote symbols (" ") in a str? Let us try issuing the following block of code that uses a str to display a quote:

print("Marcus Tullius Cicero once said "the beginnings of all things are small."") 
  Input In [12]
    print("Marcus Tullius Cicero once said "the beginnings of all things are small."")
          ^
SyntaxError: invalid syntax. Perhaps you forgot a comma?

Even without reading the outputted SyntaxError, you can quickly tell there are problems because each time a quote symbol is used, the Python shell interprets this as the start or end of a str. To fix this problem, we can use the double quote escape character, \", to tell the Python shell that we simply want to use the " symbol as a character within a str object. The modified block of code below shows how \" works:

print("Marcus Tullius Cicero once said \"the beginnings of all things are small.\"") 
Marcus Tullius Cicero once said "the beginnings of all things are small."

There are numerous escape characters available to use. Below is a table that contains a few useful escape characters relevant for data science applications (taken from the official Python documentation):

Escape Character

Result

\\

Backslash

\'

Single quote '

\"

Double quote "

\a

Bell (BEL)

\b

Backspace (BS)

\f

Form feed (FF)

\n

Newline / linefeed (LF)

\r

Carriage return (CR)

\t

Horizontal tab (TAB)

\v

Vertical tab (VT)

\nnn

Character with octal value nnn (e.g., \075 gives =)

\xNN

Character with hex value NN (e.g., \x3D gives =)

5.5. More with print()#

The function print()) has been extremely useful so far as it has allowed us to display information in the Python terminal. As we use it more, we are noticing that there are more things going on “under the hood” with this modest function. Take in point the earlier discussion about the \n character. We noticed that print() appears to be automatically applying a \n character after each function call. Let us look a bit deeper into the print() function.

Imagine we have four names stored as variables that we want to output. One way we can try doing this is to utilize the + route from earlier. Let us try doing this and see what we get:

name1 = "Issac Newton"
name2 = "Paul Scherrer"
name3 = "Rosalind Franklin"
name4 = "Hendrik Lorentz"

print(name1 + name2 + name3 + name4)
Issac NewtonPaul ScherrerRosalind FranklinHendrik Lorentz
print(name1, name2, name3, name4)
Issac Newton Paul Scherrer Rosalind Franklin Hendrik Lorentz

Here, each name is listed in the order we want. Also notice that print() by default places a separating space character between each object. This “separator” character can be changed in print() by issuing the optional argument sep into the function call. For example, let us change the separator to a , symbol for better readability:

print(name1, name2, name3, name4, sep =",")
Issac Newton,Paul Scherrer,Rosalind Franklin,Hendrik Lorentz

Close! We now got ,, but we have lost the space character. We can easily fix this by issuing , (i.e., comma and then space) as the sep argument:

print(name1, name2, name3, name4, sep=", ")
Issac Newton, Paul Scherrer, Rosalind Franklin, Hendrik Lorentz

Now we have an easily readable list of names! The sep argument can also accept multiple values. For example, we can also issue the characters , and (i.e., a space character) separately to get the same output:

print(name1, name2, name3, name4, sep="," " ")
Issac Newton, Paul Scherrer, Rosalind Franklin, Hendrik Lorentz

If we want to display each name on its own line rather than in a single row, we have two options. The first option is to call print() separately four times for each variable. We have seen this method implemented in previous examples throughout the guide. We can also achieve our goal with a single print() command by changing the sep argument to \n. The block of code below demonstrates this:

print(name1, name2, name3, name4, sep="\n")
Issac Newton
Paul Scherrer
Rosalind Franklin
Hendrik Lorentz

Here we get exactly the output format we want with a single print() call. Another useful print() argument is end, which adds to the end of the function call a user defined str. The default value for end is \n, which is the reason why in our previous examples multiple calls of print() led to text being displayed on new lines. Let us append our current print() example so that an additional row of tilde (~) symbols comes after name4. Running the following block of code gives us:

print(name1, name2, name3, name4, sep="\n", end="~~~~~~~~~~~~~~~~")
Issac Newton
Paul Scherrer
Rosalind Franklin
Hendrik Lorentz~~~~~~~~~~~~~~~~

Not exactly what we wanted as we wrote over the default value for end, which is \n. Similar to our discussion about the sep argument, we can issue multiple values to end. Therefore, we can fix our problem by first issuing \n and then our tilde symbols:

print(name1, name2, name3, name4, sep="\n", end="\n" "~~~~~~~~~~~~~~~~")
Issac Newton
Paul Scherrer
Rosalind Franklin
Hendrik Lorentz
~~~~~~~~~~~~~~~~

Now we get exactly what we want. As this example has shown, there are many ways to tune how print() output objects in Python. Furthermore, print() can also display more than just int, float, and str objects. For example, instead of having four separate variables for each name, we could also create a list that stores the names. The code below creates a list called names that has our previously mentioned four names:

names = ["Issac Newton", "Paul Scherrer", "Rosalind Franklin", "Hendrik Lorentz"]

Issuing print() directly on names gives the following output:

print(names)
['Issac Newton', 'Paul Scherrer', 'Rosalind Franklin', 'Hendrik Lorentz']

As seen in the output, the shell prints out the entire contents of the list to the terminal, including the necessary formatting symbols (i.e., the [ ] and , symbols). If we want to display each name individually on separate lines with an additional ending tilde line (i.e., like we did before) we can issue the following command:

print(names[0], names[1], names[2], names[3], sep="\n", end="\n" "~~~~~~~~~~~~~~~~")
Issac Newton
Paul Scherrer
Rosalind Franklin
Hendrik Lorentz
~~~~~~~~~~~~~~~~

Here, we call each value in names using their proper index value and then use sep and end arguments to tailor our output format. As a result, we can reproduce a similar output format using a completely different data class.

In addition sep and end, there are a few additional arguments for print(), but these arguments are a bit more on the advanced side of Python use. If you are interested in understanding these additional arguments, the official Python documentation has useful information about print(). All in all, print() is very useful in displaying information to the terminal. By diving a little deeper into how print() “functions”, we have learned new ways to create effective and elegant output messages.

5.5.1. Example: Mailing address#

The United States Postal Service uses the following format for sending and receiving mail:

name
street address
city, state ZIP code

Using what you now know about escape characters and the print() function, display your mailing address to the terminal. In addition, add a final line of text that displays the string ------#### to mark the end of your mailing address.


Solution:

As seen in the block of code below, we first create str-based variables for each of the necessary mailing address values. Next, we enter these variables into print() and use the sep and end arguments to provide the necessary line returns and the final chain of ------#### characters. Note that the () surrounding the entry for the city, state, and ZIP code is entirely optional and is only used for readability purposes.

name = "Goldy Gopher"
address = "421 Washington Ave SE"
city = "Minneapolis"
state = "Minnesota"
zipcode = "55455"

print(name, address, (city + ", " + state + " " + zipcode), 
      sep="\n", end="\n" "------####")
Goldy Gopher
421 Washington Ave SE
Minneapolis, Minnesota 55455
------####

5.6. Incorporating other data types into strings#

Programming for engineers often involves displaying results in a human-readable way. For instance, we may want the terminal to output a statement that starts with a str of useful words, then a number that is float object, and finally end with another str of words. Therefore, it becomes necessary to find effective ways to combine multiple data classes together when issuing a print() command.

Imagine we want the Python shell to display the message “The Curie temperature of the sample is 123 K”. In this scenario we have the temperature value of 123 stored as an int variable named curie_temp. One way we could do this is to send the message as multiple objects into print() that are separated by , symbols (similar to our earlier example about displaying a list of names). The code below does this route by first declaring curie_temp and then issuing the appropriate print() command:

curie_temp = 123
print("The Curie temperature of the sample is", curie_temp, "K.")
The Curie temperature of the sample is 123 K.

From what we now know about print(), we can quickly understand what is going on here. There are three objects being passed through print() in succession: a str that has the message up to the temperature, the variable curie_temp, and then finally an ending str that has the units and a period. Since the default sep value in print() is a space ( ), the sentence is correctly formatted.

Another way we can display this message is to create a str that combines all three parts together (let us call this object message) and then issue the print() command. The following block of code does this in two steps:

message = "The Curie temperature of the sample is " + str(curie_temp) + " K."
print(message)
The Curie temperature of the sample is 123 K.

Here we use our previously discussed function, str(), to convert curie_temp to a str when combining all three parts together using + symbols. Technically, this all can be done in one line of code by issuing this command within print(), but the code is a bit harder to read.

5.6.1. %-formatting of strings#

While the previous methods work, they are a bit cumbersome as we have to issue multiple objects in succession. Ideally, we would like to issue just one object to print() that is properly formatted and can handle multiple data classes at once. Fortunately, Python can do this with the str class via two common formatting methods. The first method, which is sometimes called “%-formatting”, uses the % operator as a formatting guide when injecting an object into the str. This formatting style originated in older coding languages (e.g., C-based languages), and has been adapted for the Python language. The following block of code issues our previously desired statement but now using %-formatting:

print("The Curie temperature of the sample is %d K." % curie_temp)
The Curie temperature of the sample is 123 K.

As seen in the code above, there are two important pieces of the code worth mentioning. First is the use of the %d symbol instead of the int value 123. Here, the % character is issued as an operator and not as a percentage symbol in the string due to the subsequent d character. The Python shell interprets the %d symbol to mean that an int object should be presented in a “decimal format”, which to us means present the object as a base 10 integer. In short, the %d symbol can be thought of as a placeholder for an object that also contains information about how this object should be presented. After the string ends, there is an additional section of code which has the statement % curie_temp. It is here where the shell learns what the %d placeholder represents.

Hey! Listen!

As engineers, the phrase “decimal format” for an integer reads as a misnomer since “decimal” to us means a value with a decimal point (e.g., a float object in Python). As you will see in the upcoming table, this is done because Python can represent int objects in different number bases (e.g., binary base = base 2, octal base = base 8, decimal base = base 10, and hex base = base 16). So the phrase “decimal integer” means present the object as a base 10 integer (i.e., our normal number base!) in Python.

It is important to recognize that %-formatting is a formatting standard for the str class and is not tied to print() . To see this, let us repeat the above example but separate the %-formatting step from the print() step:

curie_message = "The Curie temperature of the sample is %d K." % curie_temp
print(type(curie_message))
print(curie_message)
<class 'str'>
The Curie temperature of the sample is 123 K.

Just for good measure we have also issued type() to confirm that our message curie_message is indeed a str. Therefore, we can use %-formatting when constructing str objects!. The %-formatting method can be extended to allow for multiple non-str objects to be injected into a str. This is done by first issuing multiple %-based placeholder symbols in the str, and then listing the multiple objects to be injected after the str as a tuple. The block of code below shows this off when displaying the lattice parameter of Cu:

sample = "Cu"
lattice_parameter = 0.36150
units = "nm"

print("The lattice parameter of %s is %f %s." % (sample, lattice_parameter, units))
The lattice parameter of Cu is 0.361500 nm.

Notice that we have issued two more presentation-based operators: %s and %f. The %s operator tells the shell that a str based object will be placed into the main str object. The %f operator tells the shell that a float object will be placed into the str and presented in fixed-point / floating point notation. The order of the objects in the tuple does matter as they must be chronological in order. If not, the output may be either nonsensical or even present an error:

print("The lattice parameter of %s is %f %s." % (lattice_parameter, sample, units))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [31], in <cell line: 1>()
----> 1 print("The lattice parameter of %s is %f %s." % (lattice_parameter, sample, units))

TypeError: must be real number, not str

5.6.2. Digit precision#

If you look closely at the output of our previous example, you might notice something odd with the displayed lattice parameter value…it has an extra “0” at the end of the number (when compared to lattice parameter). This is due to the precision level that Python tries to present a number in str form. As explained in the official Python documentation, the fixed-point presentation type (i.e., %f) by default displays six digits of precision past the decimal point. This is why the displayed number has an extra “0”.

To engineers, these digits (a.k.a. significant figures) matter. Having too few or too many extra digits is not correct. Fortunately, %-formatting allows us to easily adjust the precision level of our injected object through the use of the . symbol. The modified block of code below shows how this works:

print("The lattice parameter of %s is %.5f %s." % (sample, lattice_parameter, units))
The lattice parameter of Cu is 0.36150 nm.

Notice in this cell we have replaced the %f operator from earlier with %.5f, which tells Python to display our float object in a fixed-point notation with 5 digits of precision (i.e., 5 digits AFTER the decimal point). You can easily imagine that changing this value from 5 to another precision level will cause the displayed value of lattice_parameter have different levels of precision.

5.6.3. Other useful formatting options#

So far we have shown how to inject str, int, and float objects into a str through the use of %s, %d, and %f, respectively. There are a few other ways Python can present these objects in a str. Using our lattice parameter example from before, we can have Python represent lattice_parameter as an exponential number by using the %e formatting operator:

print("The lattice parameter of %s is %.4e %s." % (sample, lattice_parameter, units))
The lattice parameter of Cu is 3.6150e-01 nm.

In the above example, the precision is set to 4 digits AFTER the decimal point, which retains the original significant figures of lattice_parameter.

What if we try to format lattice_parameter as a decimal integer using %d from before? Let us look at the output from the block of code below:

print("The lattice parameter of %s is %d %s." % (sample, lattice_parameter, units))
The lattice parameter of Cu is 0 nm.

Not good. Even if we increase the precision to 5, we get a similar result:

print("The lattice parameter of %s is %.5d %s." % (sample, lattice_parameter, units))
The lattice parameter of Cu is 00000 nm.

This output is technically correct since Python is presenting the value of lattice_parameter as an integer (i.e., a whole number). Since the value of lattice_parameter is 0.36150, the shell will only display the value BEFORE the decimal point. It is important to be mindful in how you want to display your non-str objects in a str.

As we have seen so far, there are numerous ways to present objects in a str. The object’s class will dictate the possible presentation options available. Below are presentation options (also called presentation types) tables available for str, int, and float objects (taken from the official Python documentation):

5.6.3.1. str presentation types#

str Presentation Type

Meaning

s

String format: Default presentation type.

None

Same as s.

5.6.3.2. int presentation types#

int Presentation Type

Meaning

b

Binary format: Outputs number in base 2.

c

Character: Integer presented as corresponding unicode character.

d

Decimal format: Outputs number in base 10.

o

Octal format: Outputs number in base 8.

x

Hex format: Outputs number in base 16. Lower-case letters used for digits above 9.

X

Hex format: Outputs number in base 16. Upper-case letters used for digits above 9.

n

Number format: Similar to d but uses the computer’s setting for the appropriate number
of separator characters.

None

Same as d.

5.6.3.3. float presentation types#

float Presentation Type

Meaning

e

Scientific notation: Number that is normally presented as \(m\cdot10^n\), where \(m\) is the significand that is multiplied by 10 raised to the exponent \(n\), will be presented as men with e representing the power of 10 base. Default precision is 6 digits after the decimal point.

E

Scientific notation: Similar to e but with E representing the power of 10 base.

f

Fixed-point notation: Number is presented with a decimal point. Default precision is 6 digits after the decimal point.

F

Fixed-point notation: Similar to f but converts nan (not a number) to NAN and inf (infinity) to INF.

g

General notation: Python shell algorithmically determines to display float in either scientific notation (e) or fixed-point notation (f) based on the size of the number and its precision level.

G

General notation: Similar to g but uses E if the number gets too large.

n

Number notation: Similar to g but uses the current computer’s setting for the appropriate number of separator characters.

%

Percent notation: Multiplies number by 100 and displays using the fixed-point notation f.

None

Same as g.

5.6.4. f-formatting of strings#

As mentioned above, %-formatting of strings is a carryover from older languages. As the Python language has developed over the years, different methods of formatting str objects have been created. The release of Python version 3.6 (release date: 12/23/2016) included a new way to format str objects. This new style goes by multiple names which includes: f-formatting of strings, formatted string literal, and f-string. This newer method utilizes the presentation types and precision options of %-formatting but in a clearer way. To see how f-strings works, let us rewrite our previous lattice parameter strin f-string notation:

text = f"The lattice parameter of {sample} is {lattice_parameter:0.5f} {units}."
print(text)
The lattice parameter of Cu is 0.36150 nm.

As seen in the above code, there are two changes from %-formatting. First, an f character is placed before the " character when declaring the str. This tells Python to format the following str object with f-string formatting. Second, the % placeholder symbols have been replaced with { } characters that surround the variables to be displayed. This change makes it much easier to recognize where a variable will be displayed in a str object.

The f-string formatting method also allows one to either explicitly state the presentation type for an object or allow Python to make the decision based on the object’s class. In the case of explicitly choosing a presentation type, one simply uses the : symbol followed by the precision number (optional) and the presentation type. This is done in the statement {lattice_parameter:0.5f}. Here, we tell Python to display lattice_parameter in fixed-point notation using 5 digit precision. In the cases of sample and units, no presentation type (i.e., the None type) or precision level were explicitly specified. In these cases, a default presentation type is chosen by Python based on the variable’s class. The three tables from earlier note the default presentation type in the None rows.

One can even do simple operations within the { } symbols. The example below shows how f-strings can be used in str construction that include numerous variables and in-line operations:

mass = 2.5
mass_units = "kg"
accel = 5.73
accel_units = "m*s^-2"

message = f"Using Newton's second law, F = ma, a {mass} {mass_units} object accelerating at {accel} {accel_units} will have a force of {mass * accel} N."
print(message)
Using Newton's second law, F = ma, a 2.5 kg object accelerating at 5.73 m*s^-2 will have a force of 14.325000000000001 N.

As seen in the example above, we get the correct str for the most part, except for the significant figures on the value of the force (14.325000000000001). This is easily fixed by adding :.3f after mass * accel to state that we want this multiplied value to be presented in fixed-point notation with 3 digits of precision. The modified code is shown below:

message = f"Using Newton's second law, F = ma, a {mass} {mass_units} object accelerating at {accel} {accel_units} will have a force of {mass * accel:.3f} N."
print(message)
Using Newton's second law, F = ma, a 2.5 kg object accelerating at 5.73 m*s^-2 will have a force of 14.325 N.

Overall, f-string formatting provides a very human-readable way to construct str objects from other data classes.

5.6.5. Example: A fancier way#

In a previous example, we calculated the mass of an aluminum bar and reported this value to the terminal. At that time we only knew how to display just the mass value without any units or explanation. Now that we know more about the str class and the print() function, repeat this example but now have the terminal display the answer using the following sentence:

Assuming a density of {density} g/cm^3, a {volume} cm^3 bar of aluminum will have a mass of {mass} g.

where {density}, {volume}, and {mass} are the stored values for the density, volume, and mass, respectively. All numbers should be displayed in floating point notation to a tenths position of resolution. Display this sentence first using the %-formatting notation and then using the f-formatting notation.


Solution:

As seen in the code block below, the first half of the code is the same from the earlier example. The second half implements the print() function calls with both formatting notations. Since the problem statement requires us to display the values as floating points numbers with a tenths position of resolution, we append the .1f command to each variable call.

density = 2.7
volume = 4.5
mass = density * volume

print("%-formatting version", end="\n")
print("Assuming a density of %.1f g/cm^3, a %.1f cm^3 bar of aluminum will have a mass of %.1f g." % (density, volume, mass))

print("f-formatting version", end="\n")
print(f"Assuming a density of {density:.1f} g/cm^3, a {volume:.1f} cm^3 bar of aluminum will have a mass of {mass:.1f} g.")
%-formatting version
Assuming a density of 2.7 g/cm^3, a 4.5 cm^3 bar of aluminum will have a mass of 12.2 g.
f-formatting version
Assuming a density of 2.7 g/cm^3, a 4.5 cm^3 bar of aluminum will have a mass of 12.2 g.

5.7. float notation styles in strings#

The float data class is one of the most commonly used data types for engineering applications. Let us spend the remainder of this lesson looking in more detail at three common presentation types for float objects. These three types can be found in our earlier displayed table, and for readability purposes we will use f-string formatting in the following examples.

5.7.1. Fixed-point notation#

Fixed point notation (presentation type: f) presents a float object in decimal format. If no precision is given, Python defaults to 6 precision digits AFTER that decimal point. If a precision value is provided, then the number of displayed digits is cut off to the precision level. The example below displays a float variable called alpha, which has a value of 125.3956, using fixed-point notation with various levels of precision:

alpha = 125.3956
print(f"Default fixed-point notation has 6 decimal point precision: {alpha:f}")
print("\n")
print(f"Fixed-point notation with 1 decimal point precision: {alpha:.1f}")
print(f"Fixed-point notation with 2 decimal point precision: {alpha:.2f}")
print(f"Fixed-point notation with 3 decimal point precision: {alpha:.3f}")
print(f"Fixed-point notation with 4 decimal point precision: {alpha:.4f}")
Default fixed-point notation has 6 decimal point precision: 125.395600


Fixed-point notation with 1 decimal point precision: 125.4
Fixed-point notation with 2 decimal point precision: 125.40
Fixed-point notation with 3 decimal point precision: 125.396
Fixed-point notation with 4 decimal point precision: 125.3956

5.7.2. Scientific notation#

Scientific notation (presentation type: e) presents a float object in the format \(m*\cdot10^n\), where \(m\) is the significand that is multiplied by 10 raised to the exponent \(n\). Python by default will present the significand with a digit in the ones position, followed by a decimal point, and ending with additional values based on the precision level. If no precision value is provided, Python defaults to 6 precision digits AFTER that significand’s decimal point. If a precision value is provided, the number of displayed digits AFTER the decimal point in the significand is cut off to the declared precision level. The code below again displays alpha but now in scientific notation with various levels of precision:

alpha = 125.3956
print(f"Default scientific notation has 6 decimal point precision: {alpha:e}")
print("\n")
print(f"Scientific notation with 1 decimal point precision: {alpha:.1e}")
print(f"Scientific notation with 2 decimal point precision: {alpha:.2e}")
print(f"Scientific notation with 3 decimal point precision: {alpha:.3e}")
print(f"Scientific notation with 4 decimal point precision: {alpha:.4e}")
print(f"Scientific notation with 5 decimal point precision: {alpha:.5e}")
print(f"Scientific notation with 6 decimal point precision: {alpha:.6e}")
Default scientific notation has 6 decimal point precision: 1.253956e+02


Scientific notation with 1 decimal point precision: 1.3e+02
Scientific notation with 2 decimal point precision: 1.25e+02
Scientific notation with 3 decimal point precision: 1.254e+02
Scientific notation with 4 decimal point precision: 1.2540e+02
Scientific notation with 5 decimal point precision: 1.25396e+02
Scientific notation with 6 decimal point precision: 1.253956e+02

5.7.3. General format notation#

General format notation (presentation type: g) is somewhat of a hybrid between fixed-point and scientific notations. This notation algorithmically decides to present the float object in either fixed-point notation or scientific notation based on size of float number and the level of precision. Details on how Python decides which format to use can be found in the official Python documentation. The code below now displays alpha in general format notation with various levels of precision:

alpha = 125.3956
print(f"Default general notation has 6 significant digit precision: {alpha:g}")
print("\n")
print(f"General notation with 1 significant digit precision: {alpha:.1g}")
print(f"General notation with 2 significant digit precision: {alpha:.2g}")
print(f"General notation with 3 significant digit precision: {alpha:.3g}")
print(f"General notation with 4 significant digit precision: {alpha:.4g}")
print(f"General notation with 5 significant digit precision: {alpha:.5g}")
print(f"General notation with 6 significant digit precision: {alpha:.6g}")
Default general notation has 6 significant digit precision: 125.396


General notation with 1 significant digit precision: 1e+02
General notation with 2 significant digit precision: 1.3e+02
General notation with 3 significant digit precision: 125
General notation with 4 significant digit precision: 125.4
General notation with 5 significant digit precision: 125.4
General notation with 6 significant digit precision: 125.396

5.8. Concluding thoughts#

In this lesson, we developed a deeper understanding in the str class and the print() function in order to make more human-readable outputs to the terminal. We first demonstrated how a str object can be thought of as a sequence of characters, and therefore, can be indexed and combined. Next, we introduced the newline character, \n, and other escape characters to make str objects more readable. We then explored print() in more detail, and finished off by learning how to create more complex str objects using %-formatting and f-formatting techniques. Using these simple, but effective, strategies will allow us to make more informative and impactful terminal outputs.

5.9. Want to learn more?#

Python Software Foundation - Standard Library Types
Python Software Foundation - String
Python Software Foundation - Formatted String Literals (f-formatting)
W3Schools - Python Escape Characters
Python Software Foundation - print() Function
W3Schools - Python print() Function
European Southern Observatory (ESO) - ASCII Character Conversion Chart (useful for hex format)
University of Washington, Department of Atmospheric Sciences, Paul Wessel - Chart of Octal Codes for Characters
RapidTables - Hexadecimal to Decimal Converter