Braithwaite I/O

Python 3.6 f-Strings

02 November 2018

 

f-strings are TOTALLY AWESOME!

In [1]:
website = 'Braithwaite I/O'

f'Welcome to {website}!'
 

I found out about them at PyCon Canada 2017 at Mariatta Wijaya keynote.

In [15]:
from IPython.display import HTML
HTML('<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/kGd1TVfP_Ds" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>')
Out[15]:
 

They also support expressions inside the { }

In [3]:
f'Welcome to {website.upper()}!'
 

Even dict

In [4]:
portfolio = {'AAPL': 222.77, 'RHT': 122.31, 'GOOGL': 1111.77}
In [5]:
f'${portfolio['GOOGL']}USD'
 
  File "<ipython-input-5-552a7f3505aa>", line 1
    f'${portfolio['GOOGL']}USD'
                       ^
SyntaxError: invalid syntax
 

While that's a little embarrassing...

In [6]:
f"${portfolio['GOOGL']}USD"
Out[6]:
'$1111.77USD'
 

But look what else you can do...

In [7]:
f"${portfolio['GOOGL']:,}USD"
Out[7]:
'$1,111.77USD'
 

Hey I heard you like dates and times...

In [8]:
import datetime

NOW = datetime.datetime.now()

f'This notebook was run on {NOW:%d %B %Y} at {NOW:%H:%M}!'
Out[8]:
'This notebook was run on 02 November 2018 at 08:22!'
 

You can use them in class...

In [9]:
class Drink:
    def __init__(self, name, caffine):
        self.name = name
        self.caffine = caffine

    def __str__(self):
        return f'{self.name}'

    def caffine_for_quantity(self, size=100000):
        return (
            f'{self.name} has {self.caffine*size:.0f} '
            f'mg for {size/1000:.0f} grams.'
        )
In [10]:
coffee = Drink('Coffee', .0004)

coffee.caffine_for_quantity()
Out[10]:
'Coffee has 40 mg for 100 grams.'
In [11]:
f'{coffee.caffine_for_quantity(459732)}'
Out[11]:
'Coffee has 184 mg for 460 grams.'
In [12]:
import timeit

format_funcs = {
    'f-strings': """
def format(superhero, rank):
    return f'{superhero} has a rank of {rank}!'
""",
    '%-formatting': """
def format(superhero, rank):
    return '%s has a rank of %s!' % (superhero, str(rank))
""",
    '.format()': """
def format(superhero, rank):
    return '{} has a rank of {}!'.format(superhero, str(rank))
""",
    'concatenation +': """
def format(superhero, rank):
    return superhero + ' has a rank of ' + str(rank) + '!'
""",
    'concatenation ()': """
def format(superhero, rank):
    return superhero, ' has a rank of ', str(rank), '!'
"""
}

test_func = """def test_format():
    for superhero in ('Wonder Woman', 'Supergirl', 'Batman', 'Robin'):
        for rank in range (1, 101):
            format(superhero, rank)
"""

data = []

for key, func in format_funcs.items():
    data.append({
        'method': key,
        'time': float(timeit.timeit('test_format()', func + test_func, number=10000))
    })
In [13]:
%matplotlib inline
import pandas as pd

df = pd.DataFrame([
    {'method': 'f-strings', 'time': 1.2825216680000153},
    {'method': '%-formatting', 'time': 2.282235770999989},
    {'method': '.format()', 'time': 2.983771015000002},
    {'method': 'concatenation +', 'time': 1.9718771689999812},
    {'method': 'concatenation ()', 'time': 1.402194948999977}
])
 

and it's fast...

In [14]:
df.sort_values('time').plot(
    kind='barh', 
    x='method', 
    y='time', 
    figsize=(12, 6), 
    fontsize=14, 
    legend=False
)
Out[14]:
<matplotlib.axes._subplots.AxesSubplot at 0x119895630>
 
 

Want to work with me?

GrantMatch is looking for a Student Co-op -- Junior Software Developer

https://fairtax.ca/careers/junior-software-developer/