An Overview of Python, Flask, and Flask-Assistant


This past year I've been developing a python package called Flask-Assistant. It's goal is to serve as a framework for easily creating Voice/Conversational User interfaces. The framework uses API.AI for it's natural language processing and integration into other platforms.

One awesome thing I didn't expect was the amount of people it attracted who were new to python or programming in general.

So here's a very lightwieght overview of the ecosystems you'll be working with when you use flask-assistant to create apps/bots/virtual-assistants or whatever else you want to call them.

Python

This is by no means a great turorial for python. I am leaving out a lot of important fundamentals, that you will most defintiely need as you learn to program.

Here, I am only providing the bare minimum needed to get started with flask-assistant.

Python is a programming language that you need to have installed on your computer. (Almost) eveything you do with flask-assisatant will be written in this language.

Also, we're going to use python 3! Just forget about python 2.

Absolute beginners (or anyone) should check out these resources:

  • Automate the Boring Stuff

    Great for the absoulte beginner. Walks you through the python instalation, basics Each chapter guides you through creating a program that is actually useful. This book gave me a much needed start-to-finish understanding of how lines of code become the program you have in your head. Check this out to advance from "I know what functions are" to "I know how to create a program to solve a probelm I have."

  • Hitchiker's Guide to Python

    The essential guide written by the Python Overlord himself, Kenneth Reitz. This will give you a great foundation for setting up and writing python using best practices.

Installing Python

Before we do anything you're going to need python on your machine. There are plenty of resources out there for installing, but this guide should do help just fine.

Virtual Environments

Although they aren't necessary its highly reccommended to use them.

In addidtion to the python you just installed, your machine comes with its own python version that it needs to do all its own fancy stuff. As you begin working on different projects, you'll be installing a lot of third party libraries. The point of virtual enevironemtns is that it keeps each project's dependencies and interpretor isolated from your other projects (AND YOUR MACHINE's python). Your machine uses it's own python version to do lot's of important things that make your computer work properly, so you dont want to dirty it up with things it doesnt need.

There's a few ways to manage virtual environments. I use pyenv, but honestly just chose the one that seems the simplest to you:

The Basics

Python offers a very simple syntax that makes it pretty easy to get going. If you're new to programming, it may feel a bit daunting when you read about things like OOP, test driven development, generators, async/await...

Well don't worry about that stuff yet, you'll be able to pick it up when you need it. Right now, you want to focus on variables and functions.

Hello World, lets create a function!

NOTE: You're probably going to want a basic unserstanding of what python's data types are. We'll only be using the String and Integer data types in this example, but it's a really good idea to at least be aware of the other types and understand that variables can refer to a vaule that is of any data type. You can find more info here

I'm sure you've seen this in every tutorial you've read. Its a function to print to the console.

def say_hello():            
    print('Hello World')

So how do we actually use this code?

Before we get into writing our code to .py files to create full blown "programs" or "scripts", let's use python interpreter directly from the shell/command line.

In your shell you start the python interpreter like so

$ python
>>> 

This provides you with the promp >>>, meaning the shell is expecting you to enter in python code which will be read and executed by the python interpreter.

Let's make python say hello, without defining the function.

>>> print('hello world')
hello world

Now let's use the function we defined

$ python
>>> def say_hello():
...     print('hello world')
...
>>> say_hello()
hello world

Ok, this is great and all but I'm sure you don't want to write all of your code in the shell.

Open a new file in any text editor and save it as hello_world.py. Files ending in .py are python files and can be read by the python interpreter.

# use the '#' symbol to create comments
# any text following the # will not be read by the interpreter
# below is the contents of hello_world.py

def say_hello():
    print('hello world')

We have now defined the function within a file. How do we run the file with python?

Instead of starting the interpreter in the shell, we can provide the file as an argument to python, telling it "to read" the file instead of us providing the code line by line.

$ python hello_world.py

Oops! nothing happened!
That's because we only defined the function. We never told python to CALL the funtion! Python reads the code from top to bottom, so we just need to add a call to say_hello

Modify hello_world.py:

#hello_world.py

def say_hello():
    print('hello world')

say_hello()

There, now we defined the function and then added a call to the function. This is just like within the say_hello function where we call print().

Now run the program again:

$ python hello_world.py
hello world

This is fine and dandy, but what if we want to greet the user by name?

We just need to change the function to accept some arguments. To accept arguments simply declare them in the function definition.

#hello_world.py

def say_hello(first_name, last_name):
    response = 'Nice to meet you {} {}'.format(first_name, last_name)
    print(response)

Now the function accepts 2 arguments and can use them within the code it executes.

  • To use the value of the arguments we simply refer to their variables, fist_name and last_name. For now, we are assuming these arguments are both strings.

  • We then define a new variable named response using '=' which is used to store the message we are going to print to the console. This response is also a string.

  • To create the message, we used string formatting to insert our name variables into another string.

Iterating and some Data Types

Put aside the hello_world.py file for now and let's talk about a very fundamental concept: Iterables and looping.

An iterable is an object "capable of returning its members one at a time". For now, you can simply think of these as sequences. They are objects that can contain other objects.

While many objects can be considered iterable, here are two types you should know and will use most often.

Sequence Types

The following types are an ordered collection of objects

str

Strings are an ordered sequence of unicode characters and used to store textual data.

They are represented with single '' or double "" quotes.

'Howdy ol' chap'

"What's up bro! You got a problem!?!?!?"

Strings can span multiple lines by tripple quoting

"""
Dear Diary
    Today I wrote in my diary

    - xo
"""

lists

Lists are the most obvious example of an iterable. They are quite simply an ordered collection of items.

They are represented with [] brackets, and items are separated by commas

`[1, 900, 55, 3, 3, 3, 3, 22]`

Lists Elements within a list can be any data type

`[1, 'pig', 55, 'shoe', some_variable, False]`

Lists can even be nested and contain other lists

 [1, 2, 3, ['one', 'two', 'three'], ['abc', ['d', 'e', 'f']]]

Sequence Operations

Indexing

Because sequences are ordered, their elements can be accessed via their index.

The elements within a sequence are indexed starting with 0.

>>> my_list = ['a', 'b', 'c', 'd']
>>> my_str = 'abcd'

>>> my_list[0]
'a'
>>> my_str[0]
'a'
>>> my_list[2]
'c'
>>> my_str[2]
'c'

Slicing

A subset of indexes within a sequence can be accessed by slicing. Slices of a sequence can be accessed with the syntax [start, end]. It's important to realize that the end index is not included in the slice. It represents the index the subset includes up to.

If no starting index is given the slice begins at the first item (0 index). If no ending index is provided, the slice includes the rest of the sequence.

The resulting slice is a new sequence

>>> my_list = [1, 2, 3, 4, 5, 6, 7]

# up to 3rd index
>>>first_3 = my_list[:3]
>>>first_3
[0, 1, 2]

# original sequence unchanged
>>>my_list
[1, 2, 3, 4, 5, 6, 7]

# 1st through 5th index
>>> my_list[1:6]
[2, 3, 4, 5, 6]

Length

The built in len() function can be called on a sequence to return its length.

>>> len([1, 2, 3, 4])
4

Notice that because indexing starts at zero, if we try to access the 4th INDEX of a sequence with length of 4 we receive an IndexError.

>>> sequence = [1, 2, 3, 4]
>>> sequence[4]
...
IndexError: list index out of range

Immutable vs Mutable

While strings and lists are similar in many regards, a key difference is that strings are immutable, while lists are mutable.

Mutable means the elements within a sequence can be modified, while immutable means the elements cannot be modified.

With lists, we can do things like

>>> animals = ['dog', 'cat', 'fish']

# change the element at the 2nd index
>>> animals[2] = 'bird'

>>> animals
['dog', 'cat', 'bird']

# add and remove items
>>> animals.append('moose')
>>> animals.remove('cat')

>>> animals
['dog', 'bird', 'moose']

# use extend to add each element of a new list
>>> animals.extend(['walrus', 'mouse'])
>>> animals
['dog', 'bird', 'moose', 'walrus', 'mouse']

Strings can not be handled the same way

>>> s = 'animal'
>>> s[2] = 'x'
TypeError: 'str' object does not support item assignment

Instead you can create new strings by assigning the results of a string method to a variable

>>> s = 'animal'

# string methods return a new string,
# not change the string itself
>>> s.upper()
'ANIMAL'
>>> s.replace('l', 'x')
'animax'

>>> s
'animal'

# assign result of upper() to variable
>>> new_s = s.upper()

>>> new_s
'ANIMAL'
>>> another_s = new_s.replace('A', 'x')
>>> another_s
'xNIMxL'

Create new strings from other strings

>>> s1 = 'hello '
>>> s2 = 'ladies and '
>>> s3 = 'gentlemen'

>>> greeting = s1 + s2 + s3

>>> greeting
'hello ladies and gentlemen'