################################################################################################################
#
# A Brief Introduction to Python f-Strings
# f-Strings are used in Python to "pretty print" (i.e. format) printed results.
#
# Here's a typical Python print statement with very little print formatting:
myVar1 = 21.3
myVar2 = -5.7
myVar3 = myVar1 * myVar2
print(myVar3)
#    or    
print("The product of myVar1 and myVar2 is: ", myVar3)

print("################################################################################################################")
# f-Strings give us much more capability in formatting and therefore conveying the results of our programs.
# For a nice introduction to f-Strings check out:
#    http://cissandbox.bentley.edu/sandbox/wp-content/uploads/2022-02-10-Documentation-on-f-strings-Updated.pdf
#
import math                            # import Python's "math" module
import sys
variable = math.pi                     # set "variable" = the math module very accurate representation of pi.

print(f"Using Numeric {variable = }")  # The name of the variable you're printing goes in {} (curly braces).
                                       # We're using a 25 character wide field.
print(f"|{variable:25}|")              # Here we the vertical bar character known as "pipe" before and after.
print(f"|{variable:<25}|")             # Here we left   justify the printed value.
print(f"|{variable:>25}|")             # Here we right  justify the printed value.
print(f"|{variable:^25}|\n")           # Here we center justify the printed value.

variable = sys.version                 # Here we do the sames things with a string variable
variable = "Python " + variable[0:6]   # We form the string variable from the current version of Python.
print(f"Using String {variable = }") 
print(f"|{variable:25}|") 
print(f"|{variable:<25}|") 
print(f"|{variable:>25}|") 
print(f"|{variable:^25}|") 

print("################################################################################################################")

# Here we do the same but we provide a fill character instead of just spaces.
# Our variable, variable, is still equal to "Python 3.11.5"
print(f"Using String {variable = }") 
print(f"|{variable:=<25}|") 
print(f"|{variable:=>25}|") 
print(f"|{variable:=^25}|\n") 
variable = "Python 3.11.5" 
print(f"Using String {variable = }") 
print(f"|{variable:=<25}|") 
print(f"|{variable:=>25}|") 
print(f"|{variable:=^25}|") 

print("################################################################################################################")

# Here is a summary of how to format various data types using f-Strings:
# Type  Meaning
# ----  ------------------------------------------------------------------------------------------------------------
#   s   String format—this is the default type for strings
#   d   Decimal Integer. This uses a comma as the number separator character. 
#   n   Number. This is the same as d except that it uses the current locale setting to 
#       insert the appropriate number separator characters. 
#   e   Exponent notation. Prints the number in scientific notation using the letter ‘e’ to indicate the exponent. 
#       The default precision is 6. 
#   f   Fixed-point notation. Displays the number as a fixed-point number. The default precision is 6.
#   %   Percentage. Multiplies the number by 100 and displays in fixed ('f') format, followed by a percent sign. 

variable = 10 
print(f"Using Numeric {variable = }") 
print(f"This prints without formatting {variable}") 
print(f"This prints with formatting {variable:d}") 
print(f"This prints also with formatting {variable:n}") 
print(f"This prints with spacing {variable:10d}\n") 

variable = math.pi 
print(f"Using Numeric {variable = }") 
print(f"This prints without formatting {variable}") 
print(f"This prints with formatting {variable:f}") 
print(f"This prints with spacing {variable:20f}") 

variable = 4 
print(f"Using Numeric {variable = }") 
print(f"This prints without formatting {variable}") 
print(f"This prints with percent formatting {variable:%}\n") 
variable = 403267890 
print(f"Using Numeric {variable = }") 
print(f"This prints with exponential formatting {variable:e}") 

print("################################################################################################################")

variable = 1200356.8796 
print(f"Using Numeric {variable = }") 
print(f"With two decimal places: {variable:.2f}") 
print(f"With four decimal places: {variable:.3f}") 
print(f"With two decimal places and a comma: {variable:,.2f}") 
print(f"With a forced plus sign: {variable:+.2f}\n") 

variable *= -1 
print(f"Using Numeric {variable = }") 
print(f"With two decimal places and a comma: {variable:,.2f}") 

print("################################################################################################################")

# Use of Tabs and Spacing Program 
# output is often required to be in tabular form. f-strings are very useful in formatting this kind of output. 
# The following lines produce a tidily aligned set of columns with integers and their squares and cubes, 
# using spaces to align the columns. 
# Notice the use of the field width to ensure that all the numbers are right-aligned: 
print(f'Number   Square       Cube') 
for x in range(1, 11): 
    print(f'{x:2d}       {x*x:3d}          {x*x*x:4d}') 

print("################################################################################################################")

# The tab character (\t) can also be used in an f-string to line up columns, 
# particularly when column headings are used: 
print(f'Number\t\t\tSquare\t\t\tCube') 
for x in range(1, 11):
    print(f'{x:2d}\t\t\t{x*x:3d}\t\t\t{x*x*x:4d}')
	

# Using either tabs or spacing is acceptable and may depend on which one you are more comfortable with. 
# Either way is acceptable in Python. 
# The following takes the previous program and converts x to a float() so that formatting of floating-point numbers 
# can be demonstrated: 
print(f'Number\t\tSquare\t\tCube') 
for x in range(1, 11):
    x = float(x)
    print(f'{x:5.2f}\t\t{x*x:6.2f}\t\t{x*x*x:8.2f}') 

print("################################################################################################################")

# This also demonstrates how the use of a value for width will enable the columns to line up. 
# The following program demonstrates the use of strings, decimals, and floats, as well as tabs 
# for a type of report that is often produced in a typical Python program. 
# Notice the use of the dollar sign ($) just before the variables that are to be displayed as prices. 
APPLES = .50 
BREAD = 1.50 
CHEESE = 2.25 

numApples = 3
numBread = 10 
numCheese = 6 

prcApples = numApples * APPLES 
prcBread = numBread* BREAD 
prcCheese = numCheese * CHEESE 

strApples = 'Apples' 
strBread = 'Rye Bread' 
strCheese = 'Cheese' 

total = prcBread + prcCheese + prcApples 

print(f'{"My Grocery List":^30s}') 
print(f'{"="*30}') 
print(f'{strApples:10s}{numApples:10d}\t${prcApples:>5.2f}') 
print(f'{strBread:10s}{numBread:10d}\t${prcBread:>5.2f}') 
print(f'{strCheese:10s}{numCheese:10d}\t${prcCheese:>5.2f}') 
print(f'{"Total:":>20s}\t${total:>5.2f}') 

print("################################################################################################################")
