download notebook

Fifteen-minute Friday: Code style and string formatting

files needed = None

Fifteen-minute Fridays are brief, nongraded workbooks that provide some extra practice and introduce new topics for self-guided study. This week we are working on

  1. Best practices for writing code
  2. String formatting

The solutions to the practice problems are at the end of the notebook.

Writing good code

Our goal is to learn enough python that we can do interesting/powerful/fun stuff with data. We are not here to become coding experts.

That being said, we should strive to write 'good' code. What is good code? We will talk about some specifics below, but at the highest level, good code is easy for humans to read and understand. One of python's strengths is its inherent readability.

The people who work on developing python itself publish a style guide known as PEP-8. The goal of the style guide is to get everyone to write code in ways that make the code easy to read.

The guidelines below are not exactly PEP-8. I do not want you stressing unnecessarily over style, but I do want you to keep in mind some key themes.

[You will notice that I do not always follow these rules. This is usually accidental. I am human. ]

Spacing

  1. Limit the length of a line of code to 79 characters. Having to scroll right to read a line of code is distracting. Some text editors can display a line down the screen to mark the 'edge.' [I break this rule a lot. Sorry.]

  2. Use blank lines to group related blocks of code.

  3. Put a space before and after assignment (=) and comparisons (==, !=, <, <).

  4. Put a space after a comma.

# Examples of point 3.
x = 1 + 5

if x < 10:
    print(x)

# Examples of point 4 (and point 3).
print('The value of x is', x)

x_list = [1, 3, 6, 9]

Comments

  1. Use comments when needed. Do not comment on the trivial.
  2. Comments should be complete sentences. Capitalize the first letter. Use a period at the end.
  3. Use a comment on the line before code rather than to the right of the code. [I break this rule a lot!]
  4. Use docstrings whenever you write a function. This rule will make more sense once we have introduced functions next week.
# Examples of point 1.

# Add 1 to x.   <-- No! This is obvious.
x = x +1

###########################################
### Some people use comment blocks like ###
### this to section off their code.     ###
### I use them to let readers know what ###
### each piece of a very long program   ###
### is for.                             ###
###########################################

Naming conventions

Different people, languages, and businesses use different naming conventions. The key here is to be consistent.

  1. I use all lower case letters for variables and functions and I use underscores (_) to make the names more readable.
  2. Use all capital letters to denote a constant value.
  3. Try to make function and variable names self-documenting.
# Examples of naming conventions (and spacing conventions).

# The gravitational constant in SI units. 
GRAV = 6.67430e-11

# m1 and m2 are the masses of the bodies. r is the distance between the bodies.
m1 = 100
m2 = 100
r = 20

force = GRAV*m1*m2/r**2

Bonus content: Python understands scientific notation. The number \(6.67 x 10^{-11}\) is written in python as 6.67e-11.

Practice: Writing good code

Fix up the code below.

#everyone's hours
Hrsworked_Bob =37
Hrsworked_Alice = 42
hrswored_Clarice=45.6


wage = 23.5000   # The wage.

x = Hrsworked_Bob* wage +Hrsworked_Alice*wage+wage*hrswored_Clarice

print(    'The total wage bill is',x)
# This string is from Maya Angelou's poem "Still I rise"
line = """You may write me down in history \nWith your bitter, twisted lies, \nYou may tread me in the very dirt \nBut still, like dust, I'll rise."""
print(line,'\n')

linelength =len(line)

# Print out the length of the line.
print('The line\'s length is',linelength)

String formatting

We work with text a lot – it is how most of us communicate. We print words and numbers to the screen and to files; we add text to figures to label axes and call out interesting observations; we analyze text as data.

This section takes you through the basics of string formatting using the newer python str.format() way of formating strings. String formatting can get very sophisticated, but we need only a few simple things. As usual, you can always Google for 'python string format' for more.

[There are two other ways to format strings in python. One uses the \% sign and follows from older c-style formatting. The newest is called 'f-strings'. The old-style formatting will show up sometimes, but using str.format is preferred. f-strings are good, too, but we'll stick with str.format for this course. ]

The basics

We insert variables into a string using the str.format() method.

school_song = 'Varsity'

print('The UW school song is {0}.'.format(school_song))

The 0 in {0} is the positional argument. It says to insert the 0-th (first) thing in format() in place of {0}.

Let's try this with two things to be printed.

# What kind of variable is this?
year_written = 1898 

print('The UW school song is {0}. It was written in {1}.'.format(school_song, year_written))

# The values can be outputed in any order.
print('The UW school song is {1}. It was written in {0}.'.format(school_song, year_written))

# The values can be used more than once. 
print('The UW school song is {0}. It was written in {1}. The first lyric is {0}! {0}!'.format(school_song, year_written))

Notice that .format() handled converting the int in year_written to a string.

Named placeholders

Instead of numbers, the variables to print can be given names. Very nice.

print('The UW school song is {song}. It was written in {year}.'.format(song='Varsity', year='1998'))

Formatting floats

For us, string formatting shows up most often when we want to format the output of numbers. This includes dealing with significant digits, currencies, dates, and alignment.

foo = 1/3
print(foo)

# This is the default float format.
print('foo = {0:f}'.format(foo))

The syntax is {position:format}. We have already seen how the position argument works. The format argument is a code that tells .format() how to, well, format the value.

In this case, we used the f to specify the float format. Doing so printed only six trailing digits. We can control the trailing digits and the overall width of the float, too.

print('foo = {0:5.3f}'.format(foo))

The code 5.3f means: output the number with a width of 5 'spaces' overall and 3 of the 5 spaces are to the right of the decimal point.

# Now the space reserved for the number is 8
print('foo = {0:8.3f}'.format(foo))

# The zero before the 8 prints out the leading zeros. 
print('foo = {0:08.3f}'.format(foo))

If we add a comma to the left of the decimal point 5,.2f we get commas to group digits. Since we specified two digits to the right of the decimal point, a trailing 0 is added.

print('An easy to read  big float is = {0:16,.2f}'.format(5692348925.2))

Practice: String formatting

  1. What happens if the number is larger than the width we specify? Try printing
big_float = 123456789123456.7899

to the screen with the format 5.2f. What happened?

  1. We often express numbers in percentage terms. Experiment with the {position:4.2%} format code (where the 4 and 2 are arbitrary numbers). Print each of the following to the screen:

    1. x = 0.03 as a percentage with 1 decimal place
    2. y = 0.65297 as a percentage with 2 decimal places
    3. z = 0.00056 as a percentage with 3 decimal places
  2. Suppose that we wanted our x, y, and z to line up on the decimal place.

03.000%
65.30%
00.056%

Try out the {position:04.2%} code to add leading zeros.









Solutions: Writing good code

# Everyone's hours worked. 
hrs_worked_Bob = 37
hrs_worked_Alice = 42
hrs_worked_Clarice = 45.6


wage = 23.5

x = hrs_worked_Bob*wage + hrs_worked_Alice*wage + hrs_worked_Clarice*wage

print('The total wage bill is', x)

Comments:

  1. I killed the wage comment. It's obvious. You might do the same for the hours worked comment, too. I decided to leave it in.
  2. I cleaned up the variable names and added space around the = operator.
  3. In the calculation, I used a space on each side of the equal sign and none around the multiplication. I moved the last 'wage' after the hours worked so that all three terms had the same form. I also might have written the line as
x = (hrs_worked_Bob + hrs_worked_Alice + hrs_worked_Clarice)*wage
  1. In the print statement, I removed the extra whitespace and added a space after the comma.
# This string is from Maya Angelou's poem "Still I rise."
line = """You may write me down in history
With your bitter, twisted lies,
You may tread me in the very dirt
But still, like dust, I'll rise."""

print(line,'\n')

linelength =len(line)


print('The line\'s length is', linelength)

Comments:

  1. I added a period to the first comment.

  2. The string was too long. Since it is in triple quotes, I broke the string at each line, and then removed the \n. Triple-quote string respect line breaks.

  3. I left linelength alone, but I might have made it line_length.

  4. I removed the trivial comment above the print statement and added a space after the comma.

Solutions: String formatting

# Question 1
big_float = 123456789123456.7899
print('Big float is {0:5.2f}'.format(big_float))
# Question 2
x = 0.03
print('{0:5.1%}'.format(x))

y = 0.65297
print('{0:5.2%}'.format(y))

z = 0.00056
print('{0:5.3%}'.format(z))
# Question 3
print('{0:07.3%}'.format(x))
print('{0:5.2%}'.format(y))
print('{0:07.3%}'.format(z))