Python Notes

Print

print("Hello World")
  • Can also print a variable: print(name)

  • Or print words and a variable: print("Hello " + name)

  • Can be used to figure out a type: print(type(name))

  • To print a string with an int you must type cast: print("Your age is: " + str(age))

  • An easy way to print a string with variables is an f-string: print(f"Hello {name} it's {day}")

  • When printing a boolean variable it will return True or False

  • For a print in a loop when you don’t want a new line each time, use: print(x, end=" ")

  • For a new line use \n

Variables

A variable is a container for a value. It behaves as the value that it contains.

Types

  • String: a series of characters. Ex: name = "Greyson"

  • Int: a whole number. Ex: age = 20

  • Float: a decimal number. Ex: height = 6.5

  • Boolean: True or False. Ex: on = False

Variables can be added together:

first_name = "Greyson"
last_name = "Trubia"
full_name = first_name + last_name

Multiple Assignment

Assign multiple variables at the same time in one line of code.

name, age, alive = "Greyson", 20, True

# Sets them all to 30
spongebob = patrick = sandy = squidward = 30

String Methods

print(len(name))            # length of a string
print(name.find("r"))       # position of a character within a string
print(name.capitalize())    # capitalize the first letter
print(name.upper())         # make string all uppercase
print(name.lower())         # make string all lowercase
print(name.isdigit())       # True/False - is the string a digit
print(name.isalpha())       # True/False - is the string alphabetical characters
print(name.count("e"))      # count how many times "e" appears in the string
print(name.replace("e", "a"))  # replace "e" with "a"
print(name * 3)             # print a string multiple times

Note

Correction: count() needs an argument — the character (or substring) you want to count occurrences of, e.g. name.count("e"). It does not count total characters (that’s what len() is for).

Type Casting

Converts the data type of a value to another data type.

# Temporary change
number = "5"          # string
print(int(number))    # prints the string as an int

# Permanent change
y = 2.0                # float
y = int(y)

Useful to perform mathematical operations on numbers contained in a string, or to print a number together with a string.

User Input

To ask for user input use input().

input("What is your name?")

This will ask the user for an input and wait for an entry in the console window, but doesn’t store it.

name = input("What is your name?: ")
print("Hello " + name)

User input will always be recorded as a string unless you change that:

age = int(input("How old are you?: "))  # records the input as an int

Math Functions

Use import math to access math functions. Tip: type math. to see all possible functions.

import math

round(x)          # nearest whole number
math.ceil(x)      # round up
math.floor(x)     # round down
abs(x)            # how far the number is from 0
pow(var, n)       # raise number to a power
math.sqrt(x)      # square root of a number
max(a, b, c)      # find the largest value of variables or numbers
min(a, b, c)      # find the smallest value of variables or numbers

pi = 3.14
print(math.ceil(pi))

Note

Correction: the round-up function is math.ceil(), not math.ciel().

String Slicing

Creating a substring by extracting elements from another string, using indexing [ ] or slice().

Indexing — [start:stop:step]

name = "Joe Smith"
 J  o  e     S  m  i  t  h
 0  1  2  3  4  5  6  7  8
name = "Joe Smith"
first_name = name[0:3]   # "Joe"
  • You can also do name[:3] to start from the beginning without typing the start index. The same works in reverse — leave the stop field empty and give a start index to slice to the end.

  • step is used to display every 2+ letters, starting from the first.

  • Always include the colons, even if leaving a field blank.

  • To reverse a string, set the step to -1.

Slice object — similar to indexing:

website = "https://google.com"
s = slice(8, -4)
print(website[s])   # "google"

Note

Correction: the original example used slice(7, -4), which actually includes the leading / and prints "/google". To get just "google" the start index should be 8.

If Statements

Do something only if something is true, else do something else.

age = int(input("Enter your age: "))

if age >= 18:
    print("You are now signed up")
elif age < 0:
    print("You haven't been born yet")
else:
    print("You must be 18+ to sign up")

Boolean in an if statement

for_sale = True

if for_sale:
    print("It is for sale")

No need to write a comparison — the variable itself acts as the condition.

Note

Correction: in Python, booleans are capitalized — True / False, not true / false.

Example programs referenced: calculator.py, converter.py (lbs to kg), tempconverter.py (F to C).

Logical Operators

Evaluate multiple conditions (or, and, not).

  • or — at least one condition must be true

  • and — both conditions must be true

  • not — inverts the condition

if temp > 30 or is_raining:
    print("Event is cancelled")
elif temp > 30 and is_sunny:
    print("Event is active")
elif temp > 30 and not is_sunny:
    print("It's cloudy")

Conditional Expressions

A one-line shortcut for the if/else statement. Print or assign one of two values based on a condition: X if condition else Y.

grade = 85
print("Passed" if grade > 65 else "Failed")

a = 6
b = 7
max_num = a if a > b else b
min_num = a if a < b else b

Example programs referenced: gradecheck.py.

String Methods Reference

Use print(help(str)) to list all string methods.

  • len(variable) — number of characters in a string

  • variable.find(" ") — finds the character (e.g. a space) and returns its position

  • variable.rfind("o") — finds the last occurrence of a character and returns its position; returns -1 if not found

  • variable.capitalize() — capitalizes the first letter

  • variable.upper() — makes all characters uppercase

  • variable.lower() — makes all characters lowercase

  • variable.isdigit() — True/False based on whether there are only numbers

  • variable.isalpha() — True/False based on whether there are only letters (a space does not count as a letter)

  • variable.count("e") — counts how many times that character appears

  • variable.replace("-", " ") — replaces all of the first character/string with the second

String Indexing

Indexing = accessing elements of a sequence using [ ] — [start:end:step]. The start field is inclusive, the end field is exclusive. Leave start blank to begin at the start, leave end blank to go to the end. Negative indexes count from the end.

credit_number = "1234-5678-9012-3456"

print(credit_number[0])      # "1" - first number of the sequence
print(credit_number[0:4])    # "1234" - first 4 numbers, not the dash
print(credit_number[-1])     # "6" - starts from the end
print(credit_number[::2])    # every second number, starting from the first
print(credit_number[::-1])   # the credit card number backwards

Format Specifiers

Used in an f-string to format a value, based on flags. Multiple flags can be combined without separators.

price1 = 3.14159
price2 = -987.65
price3 = 1200.34

print(f"price1 is {price1:.2f}")   # rounds to 2 decimal places -> 3.14
print(f"price2 is {price2:10}")    # pads the value to a minimum width of 10 characters
print(f"price3 is {price3:,}")     # comma thousands separator -> 1,200.34
print(f"{price1:+,.2f}")           # plus sign if positive, comma separator, 2 decimals
  • .<number>f — round to that many decimal places (fixed point)

  • :<number> — allocate that many spaces (minimum field width)

  • :03 — allocate that many spaces, zero-padded

  • :< — left justify

  • :> — right justify

  • :^ — center align

  • :+ — use a plus sign to indicate a positive value

  • := — place the sign in the leftmost position

  • ``: `` — insert a space before positive numbers

  • :, — comma separator

Note

Correction: {price2:10} pads the value itself out to a minimum width of 10 characters (numbers are right-justified by default) — it doesn’t add 10 literal spaces after the surrounding text.

While Loops

While loops execute code while some condition remains true.

food = input("Enter a food you like (q to quit): ")

while not food == "q":
    print(f"you like {food}")
    food = input("Enter another food you like (q to quit): ")

print("Done")

There must be a way to exit the loop, or it becomes an infinite loop — break can be used to escape early.

For Loops

Execute a block of code a fixed number of times. You can iterate over a range, string, sequence, etc.

Range — counting to 10 (start is inclusive, stop is exclusive):

for x in range(1, 11):
    print(x)

Counting backwards:

for x in reversed(range(1, 11)):   # 10, 9, 8 ... 1
    print(x)

# equivalent alternative
for x in range(10, 0, -1):         # 10, 9, 8 ... 1
    print(x)

Note

Correction: the original notes gave range(11, 1, -1) as equivalent to reversed(range(1, 11)). It isn’t — range(11, 1, -1) produces 11 down to 2, while reversed(range(1, 11)) produces 10 down to 1. The matching range is range(10, 0, -1).

Adding a step (a third argument counts by that amount):

for x in range(1, 11, 2):   # counts by 2s
    print(x)

Skip a specific value with continue:

for x in range(1, 21):
    if x == 13:
        continue
    else:
        print(x)   # skips 13, prints every other number

End the loop early with break:

for x in range(1, 21):
    if x == 13:
        break
    else:
        print(x)   # stops when it reaches 13

Looping over a string:

name = "Greyson"
for x in name:
    print(x)   # prints each letter on a separate line

Collections

A single variable used to store multiple values.

  • List [ ] — ordered and changeable, allows duplicates

  • Set { } — unordered, mutable (you can add/remove items), does not allow duplicates

  • Tuple ( ) — ordered and unchangeable, allows duplicates, faster; use in place of a list when you don’t need to change anything

Note

Correction: sets are mutable — you can add and remove elements from them after creation. It’s the individual elements of a set that must be immutable (hashable), not the set itself.

To see the functions available for a collection: print(dir(fruits)). To see what a function does: print(help(fruits)).

fruits = ["apple", "orange", "blueberry"]   # list

print(fruits[2])       # "blueberry"
print(fruits[0:2])     # ["apple", "orange"]

print("apple" in fruits)   # True/False - search for an item

fruits[0] = "pineapple"    # change an item by index

Note

Correction: fruits[0:2] prints ["apple", "orange"] (items at index 0 and 1) — not the whole list.

List Functions

fruits.append("strawberry")   # add to the end of the collection
fruits.remove("apple")        # remove "apple"
fruits.insert(0, "banana")    # insert "banana" at the front
fruits.sort()                 # sort the list alphabetically
fruits.reverse()              # reverse the list
fruits.clear()                # clear the list
fruits.index("apple")         # returns the index of "apple"
fruits.count("banana")        # returns how many times "banana" appears

Tuple Functions

Tuples are immutable, so they only support these two:

fruits.index("apple")    # returns 0
fruits.count("banana")   # returns 1

2D Lists

A list made up of lists. You need at least two 1D lists to build one.

groceries = [["apple", "orange", "banana"], ["celery", "carrot", "potato"]]

# or, using existing list variables
groceries = [fruits, vegetables]

If you print groceries it shows both lists on the same line, separated by a comma. Access a specific item by its coordinates:

print(groceries[0][0])   # first item in the first list

Iterate over a 2D list with a nested loop:

for collection in groceries:
    for food in collection:
        print(food)

Dictionary

A collection of {key: value} pairs. Ordered and changeable, no duplicate keys.

capitals = {"USA": "Washington D.C.", "China": "Beijing"}

print(capitals.get("USA"))   # "Washington D.C."

Check whether a key exists:

if capitals.get("USA"):
    print("That item does exist")
else:
    print("That item does not exist")

Update an existing item:

capitals.update({"USA": "New York"})

Remove the last-inserted item:

capitals.popitem()

Clear the dictionary:

capitals.clear()

Get all the keys (or values):

keys = capitals.keys()
for key in capitals.keys():
    print(key)

# same pattern, but capitals.values() for values

Print all keys with their values:

items = capitals.items()
for key, value in capitals.items():
    print(f"{key}: {value}")

Random

Must use import random.

import random

# random number
number = random.randint(low, high)

# random choice
options = ("rock", "paper", "scissors")
choice = random.choice(options)

# shuffle
cards = ["2", "3", "6", "K", "A"]
random.shuffle(cards)

Functions

A block of reusable code. Add () after the function name to invoke it.

def name():
    # code, indented underneath the function definition
    pass

name()   # calling the function

With arguments:

def hi_name(name, age):
    print(f"Hello {name}! You're {age} years old.")

hi_name("Greyson", 20)

Return Statement

Ends a function and sends a result back to the caller.

def add(x, y):
    z = x + y
    return z

print(add(3, 5))

def create_name(first, last):
    first = first.capitalize()
    last = last.capitalize()
    return first + " " + last

full_name = create_name("Greyson", "T")
print(full_name)

Default Arguments

A default value for a parameter, used when the argument is omitted. Makes functions more flexible and reduces the number of required arguments.

def net_price(list_price, discount=0, tax=0.05):
    return list_price * (1 - discount) * (1 + tax)

print(net_price(500))        # discount and tax fall back to defaults
print(net_price(500, 0.1))   # discount = 0.1, tax still defaults to 0.05

Keyword Arguments

An argument preceded by an identifier. Helps readability; order doesn’t matter.

def hello(greeting, title, first, last):
    print(f"{greeting} {title} {first} {last}")

hello(title="Mr.", greeting="Hello", first="Guy", last="Smith")

You can mix positional and keyword arguments, but keyword arguments must come after positional ones when calling the function.

Arbitrary Arguments

A varying number of arguments.

  • *args — packs multiple non-keyword arguments into a tuple

  • **kwargs — packs multiple keyword arguments into a dictionary

  • * is the unpacking operator

def add(*args):
    total = 0
    for arg in args:
        total += arg
    return total

print(add(1, 2, 4))
def print_address(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_address(street="123 fake st.", city="Detroit", state="MI", zip="54321")

Note

Correction: the kwargs example looped with for key in kwargs.items() but then referenced an undefined value. Unpack both with for key, value in kwargs.items().

Both together:

def shipping_label(*args, **kwargs):
    for arg in args:
        print(arg, end=" ")
    print()

    if "apt" in kwargs:
        print(f"{kwargs.get('street')} {kwargs.get('apt')}")
    else:
        print(f"{kwargs.get('street')}")

    print(f"{kwargs.get('city')} {kwargs.get('state')} {kwargs.get('zip')} {kwargs.get('country')}")

shipping_label("Dr.", "Spongebob", "Squarepants", street="123 Fake St.",
               city="Detroit", state="MI", zip="54321", country="US")

Note

Correction: the final print() in the original was missing its closing parenthesis and quote.

Iterables

An object/collection that can return its elements one at a time so it can be looped over. Examples: list, tuple, set, string, dictionary.

numbers = [1, 2, 3, 4, 5]
for number in numbers:
    print(number)

my_dictionary = {"A": 1, "B": 2}

for value in my_dictionary.values():        # values only
    print(value)

for key, value in my_dictionary.items():    # keys and values
    print(f"{key} = {value}")

for key in my_dictionary:                   # keys only
    print(key)

Membership Operators

Test whether a value is found in a sequence (string, list, tuple, set, dictionary), using in and not in.

word = "APPLE"
letter = input("Guess a letter in the secret word: ")

if letter in word:
    print(f"There is a/an {letter} in the word")
elif letter not in word:
    print(f"There is not a/an {letter} in the word")
students = {"Spongebob", "Patrick", "Sandy"}
student = input("Enter the name of a student: ")

if student in students:
    print(f"{student} is a student")
else:
    print(f"{student} is not a student")
grades = {"Sandy": "A", "Squidward": "B", "Spongebob": "C", "Patrick": "D"}
student = input("Enter the name of a student: ")

if student in grades:
    print(f"{student}'s grade is {grades[student]}")
else:
    print(f"{student} was not found")

List Comprehension

A concise way to create lists — more compact and often easier to read than a traditional loop: [expression for value in iterable if condition].

doubles = [x * 2 for x in range(1, 11)]
print(doubles)   # 2, 4, 6, 8 ... 20
numbers = [1, -2, 3, -4, 5, -6]
positive_nums = [num for num in numbers if num > 0]
negative_nums = [num for num in numbers if num < 0]
# sort positive and negative numbers into separate lists
grades = [85, 66, 93, 58, 97, 45]
passing = [grade for grade in grades if grade > 65]
failing = [grade for grade in grades if grade < 65]
fruits = ["apple", "orange", "banana", "coconut"]
fruits = [fruit.upper() for fruit in fruits]
print(fruits)   # each item in uppercase

fruit_chars = [fruit[0] for fruit in fruits]
print(fruit_chars)   # first letter of each fruit

Note

Correction: the positive/negative example originally used >= 0 and <= 0, which puts 0 in both lists. Using > 0 and < 0 keeps the two lists mutually exclusive.

Match-Case Statements (Switch)

An alternative to a long chain of elif statements — cleaner and more readable. Runs the code for whichever case matches the value.

def day_of_week(day):
    match day:
        case 1:
            return "It is Sunday"
        case 2:
            return "It is Monday"
        case 3:
            return "It is Tuesday"
        case 4:
            return "It is Wednesday"
        case _:
            return "Not a valid day"

print(day_of_week(1))   # "It is Sunday"

Note

Correction: the original call was day_of_week("1") (a string), which would not match case 1 (an int) and would fall through to case _. Pass the int 1 to match correctly.

Module

A file containing code you want to include in your program. Use import to include a built-in or your own module — useful for breaking a large program into reusable files.

print(help("modules"))     # list all built-in modules
print(help("math"))        # functions in a specific module, with descriptions

To make a module name shorter:

import math as m   # m can be whatever you want

To import a single function:

from math import pi

# instead of 1 * math.pi, you can now use:
1 * pi

Creating a Module

Just make a new Python file — the file name is the module name. Once imported into the main file, its variables and functions carry over.

Variable Scope

Where a variable is visible/accessible. Scope resolution order (LEGB): Local → Enclosed → Global → Built-in.

  • Local — a function can see its own variables and any passed to it, but not variables from other functions.

  • Enclosed — a function defined inside another function.

  • Global — defined outside any function; used if a variable isn’t defined locally.

  • Built-in — names provided by an imported module/library, used unless overridden by a global, enclosed, or local value of the same name.

def func1():
    print(x)   # prints 3 - uses the global variable x

def func2():
    x = 1
    print(x)   # prints 1 - the local variable takes precedence

x = 3
func1()
func2()

Note

Correction: the original example called func(1) and func(2) — neither function exists under that name, and neither func1 nor func2 takes an argument. The calls should be func1() and func2().

if __name__ == '__main__':

Indicates that a script can either be imported as a module or run standalone. When present, the functions and classes in the module can be reused without the main block automatically executing. Usually placed just before a call to main(). (Example files: script1.py, script2.py.)

Object-Oriented Programming

An object is a “bundle” of related attributes (variables) and methods (functions). A class is the blueprint used to design an object’s structure.

class Car:
    def __init__(self, model, year, color, for_sale):   # constructor
        self.model = model
        self.year = year
        self.color = color
        self.for_sale = for_sale

    # methods go inside the class
    def drive(self):
        print(f"You drive the {self.model}")

    def stop(self):
        print(f"You stop the {self.model}")

car1 = Car("Mustang", 2024, "red", False)
car2 = Car("Corvette", 2022, "blue", True)

print(car1.model)   # "Mustang"
print(car2.model)   # "Corvette"
car1.drive()         # "You drive the Mustang"

(Example files: car.py, oop.py.)

Class Variables

Shared among all instances of a class. Defined outside the constructor, so all objects created from the class share the same data.

class Student:
    class_year = 2030    # shared among all students
    num_students = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        Student.num_students += 1   # counts students as you create them

Inheritance

Allows a class to inherit attributes/methods from another class — helps code readability. Syntax: class Child(Parent):.

class Animal:
    def __init__(self, name):
        self.name = name
        self.is_alive = True

    def eat(self):
        print(f"{self.name} is eating.")

class Dog(Animal):
    def speak(self):
        print("Woof")

class Cat(Animal):
    def speak(self):
        print("Meow")

class Mouse(Animal):
    def speak(self):
        print("Squeak")

Note

Corrections: Python’s keyword is lowercase class, not Class (fixed throughout this section). Instance methods like speak also need a self parameter.

Multiple Inheritance

  • Multiple inheritance — inheriting from more than one parent class: class C(A, B):

  • Multilevel inheritance — inheriting from a parent which itself inherits from another parent: C(B) where B(A) where A is the base class.

class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(f"{self.name} is eating")

    def sleep(self):
        print(f"{self.name} is sleeping")

class Prey(Animal):
    def flee(self):
        print(f"{self.name} is fleeing")

class Predator(Animal):
    def hunt(self):
        print(f"{self.name} is hunting")

class Rabbit(Prey):
    pass

class Hawk(Predator):
    pass

class Fish(Prey, Predator):
    pass

rabbit = Rabbit("Bugz")
rabbit.eat()

Note

Correction: empty class bodies (Rabbit, Hawk, Fish) need a pass statement, or Python raises a syntax error.

Super()

Used in a child class to call a method from the parent class (superclass), extending the inherited method’s functionality. If a child method shares a name with a parent method, the child’s version overrides it — but both can still be called.

class Parent:
    def describe(self):
        print("Parent description")

class Child(Parent):
    def describe(self):
        print("Description")   # child
        super().describe()      # parent

(Example file: super.py.)

Polymorphism

From the Greek “poly” (many) + “morphe” (form) — “to have many forms.”

Two ways to achieve polymorphism:

  1. Inheritance — an object can be treated as the same type as its parent class.

  2. Duck typing — an object just needs to have the necessary attributes/methods, regardless of its actual class.