1. Basics

Comments

    • # this is a comment
    • ```
    • Three single quotation marks can be used to make multi-line comments
    • This is a comment
    • ```

Print

    • print ('hello world!'') # You can use single or double quotes throughout python

Variables

    • name = 'john'
    • authors_name = name
    • age = 30
    • print(authors_name) # output is john
    • print(age) # 30

Variable Syntax quirks

  • Can't enclose a variable name in quotations
  • Variable names can't have spaces, quotation marks, or a number as first character. They also can't be a reserved word (e.g., and, as, continue, import, or,…) but can contain one in it
  • Variable names can have numbers in the them, lowercase or uppercase letters, or underscores
  • Variable names are case sensitive
  • Best practice to break up multi-word variables with underscores (vs. camel case in JavaScript) and to use lowercase letters

Math expressions

    • x = 2
    • y = 4
    • print(x+y) # output is 6
    • print(x-y) # output is -2
    • print(x*y) # output is 8
    • print(x/y) # output is 0.5
    • x += 12 \n print(x) # output is 14
    • x -= 11 \n print(x) # output is 3
    • x *= 3 \n print(x) # output is 9
    • x += y \n print(x) # output is 13
    • print(x%y) # output is 1

Concatenating text strings

    • greeting = 'hello'
    • name = 'john'
    • print(greeting + ' ' + name) # output is hello john

Getting user info: The below code will give the user the prompt “what's your favorite” ice cream and then print it out

    • user_fav = input(“what's your favorite ice cream?”)
    • …user enters “vanilla”
    • print ('your favorite ice cream is ' + user_fav) # output is your favorite ice cream is vanilla

Changing case

    • str.lower # makes string all lower case
    • str.upper # makes string all upper case
    • str.title # capitalizes every word

General syntax quirks

  • Python executes code based on indentation so each line of code must be properly aligned in order for it to work; indentations are used to nest lines of code
  • Best practice, tab nested coded with one tab; some people prefer 4 spaces but that requires more key strokes
  • Lines of code that have nested code following it (e.g., an if-then statement), usually have a semi-colon at the end of the line
  • You can use double quotations or single quotations interchangeably. If you want to use a single quote in a string or a double quote, define the string with the other type of qoatations.
    • print(“what's your favorite ice cream?”) # output is what's your favorite ice cream?
    • print('he said, “it is vanilla”') # output is he said, “it is vanilla”

2. If Then For While

if then statements

    • if ice_cream == 'vanilla':
    • ...print('it is vanilla')

Comparison operators

    • x == y # equal to
    • x != y# not equal to
    • x > y# greater than
    • x < y# less than
    • x >= y# greater than or equal to
    • x <= y# less than or equal to

elif and else

    • if ice_cream == 'vanilla':
    • ...print('it is vanilla')
    • elif ice_cream == 'chocolate':
    • ...print('it is chocolate')
    • else:
    • ...print('it is not chocolate or vanilla')

elif and else syntax quirks

  • else gets its own line and colon at the end
  • lines after if, elif, and else are indented
  • elif is short for “else if”
  • You can have multiple elif's but only one else

And…or…

    • if tree_age > 100 and tree_height > 20:
    • ...print('that is a tall, old tree')
    • if ice_cream == 'vanilla' or ice_cream == 'chocolate':
    • ...print('that is a tasty ice cream flavor')
    • if (ice_cream == 'vanilla' or ice_cream == 'chocolate') and (ice_cream_size > 2):
    • ...print('that is a lot of tasty ice cream')

Nested if statements

    • if ice_cream == 'vanilla':
    • ...if ice_cream_size > 2:
    • ......print('that is a large, vanilla ice cream')

For loops - this goes through each element in list until end of list

    • for i in ice_cream_flavors:
    • ...print(i)
  • You can use a break statement to end a for loop
    • for i in ice_cream_flavors:
    • ...if i == 'vanilla':
    • ......print('they have your favorite flavor!')
    • ......break
  • You can nest for loops
    • for i in ice_cream_flavors:
    • ...for t in ice_cream_toppings:
    • ......print('do you want ' + i + ' ice cream with ' + t '?')
    • // output is "do you want vanilla ice cream with chocolate suace?", "do you want vanilla ice cream with sprinkles?", "do you want chocolate ice cream with chocolate suace?", "do you want chocolate ice cream with sprinkles?"
  • Integer for loop
    • for x in range(2,6):
    • ...print(x)

While loops - similar to for loop but without a pre-defined number of iterations. While loops go through a block of lines of code while a condition is true. This can be helpful for certain types of functions when you don't know how long the code should run for

    • def play_game():
    • ...user_input = input('Guess a number between 0 and 100')
    • ...while user_input != 57:
    • ......user_input = input('Wrong, guess again')
    • print('you got it right! It was 57!')

3. Lists

Basic list

    • ice_cream_flavors = [] # this is an empty list
    • ice_cream_flavors = ['vanilla', 'chocolate', 'strawberry', 'banana']
    • ice_cream_prices = [2.00, 2.25, 2.50, 2.50]

List syntax quirks

    • Use brackets to enclose a list; use curly brackets to enclose a dictionary
    • In a list, each item is called an “element”

Accessing and change elements: Lists can be accessed and changed based on the number of the element starting with zero

    • print(ice_cream_flavors[0]) // output is 'vanilla'
    • print(ice_cream_flavors[2]) // output is 'strawberry'
    • ice_cream_flavors[2] = 'mint'
    • print(ice_cream_flavors[2]) // output is 'mint'

Adding elements

    • ice_cream_flavors.append('cookie dough')
    • print(ice_cream_flavors) // output is ['vanilla', 'chocolate', 'mint', 'banana', 'cookie dough']
    • ice_cream_prices.append(2.75)
    • print(ice_cream_prices) // output is [2.00, 2.25, 2.50, 2.50, 2.75]
  • You can insert a new element in the middle of a list by using the numbering system
    • ice_cream_flavors.insert(2, “banana”)
    • print(ice_cream_flavors) // output is ['vanilla', 'chocolate', 'banana', 'mint', 'cookie dough']
  • Add two elements at once
    • ice_cream_flavors = ice_cream_flavors + ['apple', 'cherry']
    • print(ice_cream_flavors) // output is ['vanilla', 'chocolate', 'banana', 'mint', 'cookie dough', 'apple', 'cherry']

Slicing: list_name[first_element_of_slice:number_after_last_slice_element]

    • ice_cream_flavor_slice = ice_cream_flavors[1:3]
    • print(ice_cream_flavor_slice) // output is ['chocolate', 'banana']
    • ice_cream_flavor_slice = ice_cream_flavors[:3]
    • print(ice_cream_flavor_slice) // output is ['vanilla', 'chocolate', 'banana']
    • ice_cream_flavor_slice = ice_cream_flavors[4:]
    • print(ice_cream_flavor_slice) // output is ['chocolate', 'apple', 'cherry']

Deleting and removing

    • del ice_cream_flavors[5] // Delete by list index number
    • ice_cream_flavors.remove['apple']Delete by list element value
    • del ice_cream_flavors[2]
    • print(ice_cream_flavors) // output is ['vanilla', 'chocolate', 'cookie dough']

Popping elements: This takes an element of a list, deletes it from that list, and then can be used in another list

    • retired_flavors = ice_cream_flavors.pop(2)
    • retired_flavors.append(ice_cream_flavors.pop(1))
    • print(ice_cream_flavors) // output is ['vanilla']
    • print(retired_flavors) // output is ['cookie dough', 'chocolate']

Tuples: Tuples are =lists that can't be changed without redefining the entire list.

    • my_favorite_ice_cream_flavors = ('vanilla', 'cookie dough')

4. Dictionaries

Dictionaries are series of key:value pairs

    • user1 = {}# this is an empty dictionary
    • user1 = {'first_name': 'john', 'last_name':'smith', 'age':30}
    • my_favorite_ice_creams = {1:'vanilla', 2:'cookie dough',3:'chocolate chip'}

Syntax quirks

  • Keys can be numbers or words
  • Values can be any data type
  • If you are defining a long dictionary, it is good to break it into multiple lines but make sure each pair is idented,
  • Best practice: add an extra comma at the end of your dictionary when it is multiple lines so that you don't forget a comma between lines if you add an extra line; note that you don't need the comma though but python doesn't mind

Get info

    • print(user1['first_name']) // output is john

Changing value

    • user1['age'] = 31

Removing a key value pair

    • del user1['age']

Looping through values or keys or key-value pairs

    • for each_value in user1.values():
    • ...print(each_value) // output is John Smith 30 76
    • for each_key in user1.keys():
    • ...print(each_key) // output is first_name last_name age height
    • for each_key, each value in user1.items():
    • ...print(each_key + ':' + each_value) // output is first_name:john last_name:picasso age:30 height:76

List of dictionaries

    • user1 = {'user_id': 1, 'first_name': 'john', 'last_name':'picasso', 'age':30, 'height': 76}
    • user2 = {'user_id': 2, 'first_name': 'taylor', 'last_name':'swift', 'age':30, 'height': 68}
    • user3 = {'user_id': 3, 'first_name': 'tom', 'last_name':'cruise', 'age':55, 'height': 69}
    • people_list = [user1, user2, user3]

Append new dictionary to list

    • people_list.append(new_user)

Dictionary with a list

    • user1 = {'first_name': 'john', 'last_name':'picasso', 'age':30, 'height': 76, 'interests': ['coding', 'chess', 'cooking']}

Dictionary of dictionaries

  • You can replace the user_id with a key that is equal to it and a value that is equal the rest of the dictionary; you can also use a username or some other integer or string as the key for the dictionary of dictionaries
    • people_list = {
    • ...1: {'first_name': 'john', 'last_name':'picasso', 'age':30, 'height': 76},
    • ...2: {'first_name': 'taylor', 'last_name':'swift', 'age':30, 'height': 68},
    • ...3: {'first_name': 'tom', 'last_name':'cruise', 'age':55, 'height': 69},
    • }
  • You can print out the name of a specific user by using a dictionary within the dictionary
    • print(people_list[2]['first_name']) // output is taylor

5. Functions

Overview

  • Functions are blocks of code that can be used over and over again whenever they are called
  • They help you follow the principles of “DRY” = Don't Repeat Yourself
  • Basic function to see if you can drink…
    • def check_id():
    • ...age = input('how old are you?')
    • ...if age >=21:
    • ......print('you can drink')
    • ...else:
    • ......print('you can't drink')
  • You can call a function with the below; make sure it comes after the function is defined though.
    • check_id()

Pass info

  • You can pass functions through parameters, which are the variables within the parantheses of the function. Arguments are the actual values that are passed to the parameters. The below is an example of positional arguments that are passed in order.
    • def divide_numbers(x, y):
    • ...result = x/y
    • ...print result
  • You can also pass info back from the function; note that the “return” keyword returns the “result” to whatever called it
    • def divide_numbers(x, y):
    • ...result = x/y
    • ...return result
  • You can also use keyword arguments so that the order doesn't matter
    • def check_id(name, age):
    • ...if age >=21:
    • ......print(name + ', you can drink')
    • ...else:
    • ......print(name + ', you can't drink')
    • check_id(age=30, name=”john”) // output is john, you can drink
  • You can also assign a default value
    • def cash_income(salary, income_tax_rate=0.45):
    • ...print(salary * (1 - income_tax_rate))
    • cash_income(salary=200000) // output is 110000
    • cash_income(salary=200000, income_tax_rate=0.5) // output is 100000

Syntax quirks

  • Keyword parameters without defaults must come before those with them
  • You can mix positional and key word arguments but positionals must come first and positionals must be in the right order

Unknown number of args

  • You can create functions that allow an optional number of arguments by putting two asterisks before the parameter name. The function puts the optional arguments in a dictionary that you can access later.
    • def display_user_info (first_name, last_name, **extra_info):
    • ...print('Hello ' + first_name + ' ' + last_name)
    • ...for key, value in extra_info.items():
    • ......print(key + ': ' + value)
    • display_user_info(john,picasso,height=76, age=30) // output is Hello john picasso height:76 age:30
  • You can also make positional arguments optional by putting one asterisk beore them
    • def display_user_info (first_name, last_name, *age):

Syntax quirks

  • Optional arguments must come after positional arguments

Functions are variabless

    • add_numbers(x,y,z):
    • ...return x+y+z
    • multiply_numbers(x,y,z):
    • ...return x*y*z
    • total = add_numbers(x,y,z) + multiply_numbers(x,y,z)

Local vs global variables: Local variables are defined within a function and can only be used within that function; global variables are defined outside of a function and can be used anyway in that function. Try to avoid using global variables inside a function because it is confusing, instead pass them in as arguments.

6. Classes

Overview

  • Classes are templates that help you organize information. If you are creating a class called User, each food will have its own instance
  • Classes are written in a similar way as a function except by convention they begin with an uppercase letter insead of lowercase
  • Use def __init__(self, variable1, variable2): to initialize the class and then define the self attributes
    • class User():
    • ...def __init__(self, id, user_name, user_email, age):
    • ......self.id = id
    • ......self.user_name = user_name
    • ......self.user_email = user_email
  • Syntax quirk - Python assumes the arguments are positional

Create instance

  • You can create a new instance by assigning it to a unique variable. Note that the variable must be unique because it is a unique identifier.
    • user1 = User(1,johnpicasso,jpicasso@gmail.com, 30)
    • user2 = User(2,taylorswift, tswift@gmail.com,30 )

Get info

    • user_age = user1.age

Change attribute's value

    • user1.age = 31

Class methods

  • These are functions that are built into the class and can be more easily called with the instance and doesn't require you to pass along the values of the class again
    • class User():
    • ...def __init__(self, id, user_name, user_email, age):
    • ......self.id = id
    • ......self.user_name = user_name
    • ......self.user_email = user_email
    • ...def can_drink(self):
    • ......if self.age <21:
    • .........print(“user can't drink”)
    • ......else:
    • .........print('user can drink')
  • Call class method with dot notation
    • user1.can_drink() // output is user can drink

7. Data Storage and Importing Libraries

Modules

  • Python lets you import variables, classes, and functions from other python files and libraries
  • This allows you to more easily organize your python code in different files rather than have to put everything in one large file
  • It also allows you to use code from the many publicly available python libraries (e.g., SQLAlchemy, Flask, etc.)
  • Each separate python file or library is called a module
  • The below code allows you to import in the SQLAlchemy module; note that you must have installed SQLAlchemy on your machine
    • from flask_sqlalchemy import SQLAlchemy
  • The below code allows you to import in two functions (AuthError and requires_auth) from your auth.py file that is stored in your auth folder
    • from .auth.auth import AuthError, requires_auth
  • Put at the top of the file the following code to import the Movie class from the movie.py file
    • from movie import Movie

Saving as JSON

  • Create function that returns JSON in a json.py file
    • def json(self):
    • ...return {
    • ......'id': self.id,
    • ......'user_name': self. user_name,
    • ......'user_email': self. user_email,
    • ...}
  • In app.py file
    • import json
    • with open('my_file.txt', 'w' as f):
    • ...json.dump(user.json(),f)

8. Useful functions for algo's

Strings

  • Convert a number to an integer
    • ord('a') // output is 97
  • Convert an integer to a string
    • chr(97) // output is 'a'
  • String length
    • len('apple') // output is 5
  • Create an empty Boolean array
    • varB = [False] * 10
  • Access string by index value
    • s = 'apple'
    • s[0] // output is 'a'

Create an empty hash table

    • hash_table = [0]*126

Create hash table with unknown number of keys

    • 2Darray = [[1034,2],[1035,6],[1035,6]]
    • hash_table = {}
    • for e in 2Darray:
    • ...hash_table[e[0]] = 0

Create a two dimensional array / matrix

    • matrix_array= [[1,2,14],[1,12,3],[1,2,9]]

Access two dimensional array (first index is for the outer array, second is for the inner array)

    • matrix_array[0] // output is [1,2,14]
    • matrix_array[0][1] // output is 2

Define a singly linked list class

    • class NodeLL:
    • ...def __init__(self, data, next_node)
    • ......self.data = data
    • ......self.next_node = next_node
    • class LinkedList:
    • ...def __init__(self):
    • ......self.head = None

Create a singly linked list

    • p1 = Node(“George Washington”)
    • p2 = Node(“John Adams”)
    • p3 = Node(“Thomas Jefferson”)
    • prez_list = LinkedList(p1)
    • p1.next_node = p2
    • p2.next_node = p3

Create a binary search tree class

    • class NodeBST:
    • ...def __init__(self,data):
    • ......self.data = data
    • ......self.l_child = None
    • ......self.r_child = None
    • ...def binary_insert(self, node):
    • ......if self.data > node.data:
    • .........if self.l_child is None:
    • ............self.l_child = node
    • .........else:
    • ............self.l_child.binary_insert(node)
    • ......else:
    • .........if self.r_child is None:
    • ............self.r_child = node
    • .........else:
    • ............self.r_child.binary_insert(node)

Print in order a binary search tree

    • def in_order_print(self):
    • ...if self.l_child:
    • ......self.l_child.in_order_print()
    • ...print(self.data)
    • ...if self.r_child:
    • ......self.r_child.in_order_print()

Create a binary search tree using the class

    • ex_tree = NodeBST(3)
    • ex_tree.binary_insert(NodeBST(7))
    • ex_tree.binary_insert(NodeBST(1))
    • ex_tree.binary_insert(NodeBST(12))