/Introduction-to-Python

A guide of Python including introductory topics and data structures

Introduction-to-Python

An introductory guide into Python

Contents

Section 1 - Objects & Data Structures

Numbers

Python can be used as a simple calculator by inputing the desired calculation

2+1 
#3

2.0-1
#1.0

2*2
#4

3/2
#1.5

The modulus operator can also be used to obtain the remainder

7 % 4
#3

50 % 5
#0

You can also do calculations to calculate powers

2 ** 3
#8

3**2
#9

The basic order of operations follows Bidmas/Bodmas. However brackets can be used to set the order of operations

2 + 10 * 10 + 3
#105

(2 + 10) * (10 + 3)
#156

Variables

Numbers as well as many other datatypes can be assigned to a variable to reference them easily. However, there are some rules for variable names.

  • They cannot begin with a number
  • There cannot be any spaces (underscores can be used instead)
  • It cannot use any of these symbols '''.<>/?|/()!@#$%^&*~-+
  • It's generally considered best practice for names to be lowercase
  • Words that have special meaning in Python should be avoided
my_pets = 2

Python uses Dynamic Typing which means that variables can be reassigned to different data types.

my_pets = 2

my_age = ["Flapjack", "Zuko"]

There are pro's and cons for dynamic typing

Pro's

  • Easy to work with
  • Faster Development Time

Con's

  • May result in unexpected bugs
  • Need to be aware of type()
a = 10

type(a)
#int

a = 30.1
type(a)
#float

Strings

Strings are sequences of characters using either single quotes or double quotes:

print('hello')
print("world")

print("hello \nworld")
#hello
#world

print("hello \tworld")
#hello    world
Indexing

Because strings are ordered sequences, indexing and slicing can be used to grab sub-sections of the string.

Character h e l l o
Index 0 1 2 3 4
Reverse Index 0 -4 -3 -2 -1
my_name = "Rikki"

my_name[0]
#R

my_name[-1]
#i
Slicing

Slicing grabs a subsection of multiple characters of a string and has the following syntax [start:stop:step].

  • start is the index the slice starts
  • stop is the index you will go up to (but not include)
  • step is the size of each "jump"
my_name = "Rikki"

my_name[1:]
#ikki

my_name[:3]
#Rik

my_name[1:4]
#ikk

my_name[::2]
#Rki

my_name[::-1]
#ikkiR
#Reverses the string
String Properties & Methods

Strings in Python are immutable. Therefore indexing cannot be used to change individual elements of a string

To reassign a string, a new one must be created. Concatenation can also be used to make a change to the string.

name = "Vikki"

last_letters = name[1:]
#"ikki"
"R" + last_letters
#"Rikki"

The multiplication sign can also be used to carry out multiple concatenations

letter = "z"
letter * 10 
#zzzzzzzzzz

Be aware when concatenating a number with a string

2 +3 
#5

"2" + "3"
#"23"

There are various built in string methods. Some methods act "in-place" and do not affect the actual variable and would need to be reassigned e.g x = x.upper().

Method name Description Example Place
.len(x) prints length of string 11 in-place
.upper() makes entire string upper case "HELLO WORLD" in-place
.lower() makes entire string lower case "hello world" in-place
.split() or .split("r") creates a list from a string ["Hello", "World"] / ["Hello Wo", "ld"] in-place

Examples on how to use each function can be found here

String Formatting For Printing

The are times when you want to insert a variable into a string to print also known as string interpolation, for example:

my_name = "Rikki"

print("Hello " + my_name)
#Hello Rikki

However, there are many methods to do this, mainly the .format() method and f-strings (formatted string literals).

.format method
print("This is a string {}".format("INSERTED"))
#This is a string INSERTED

print("The {} {} {}".format("red","big","house"))
#"The red big house

print("The {1} {0} {2}".format("red","big","house"))
#The big red house

print("The {0} {0} {0}".format("red","big","house"))
#The red red red

print("The {b} {r} {h}".format(r = "red",b = "big",h = "house"))
#The big red house

####### Float Formatting

Float formatting allows you to adjust the precision of a floating point number and follows {value:width.precision f}. A width greater than 1 increases whitespace.

result = 100/777
#0.1287001287001287

print("The result was {r:1.3f}".format(r = result))
f-strings
name = "Rikki"

print(f"Hello, my name is {name}")
#Hello, my name is Rikki

age = 25

print(f"{Rikki} is {age} years old.")

Data Structures

Lists

Lists are ordered sequences that can be used to hold a variety of objects.They use [] and commas to seperate objects in the list e.g. [1,2,3,4,5]. Lists also support indexing and slicing, can be nested and have a variety of useful methods.

Creating Lists
my_list = [1,2,3]

my_list2 = ["String",102,25,6]

len(my_list)
#3

my_list[0]
#1

my_list[1:0]
#[2,3]
Modifying Lists
another_list = [4,5]

new_list = my_list + another_list
#[1,2,3,4,5]

new_list[0] = "ONE"

new_list
#["ONE",2,3,4,5]

new_list.append(6)
#["ONE",2,3,4,5,6]

popped_iten = new_list.pop()
#6

new_list
#["ONE",2,3,4,5]

new_pop = new_list.pop(0)
#"ONE"
Rearranging Lists
new_list
#[2,3,4,5]

new_list = ["a","e","x,"b","c"]
num_list = [4,1,8,3]

new_list.sort()
#["a","b","c,"e","x"]

num_list.sort()
sorted_list = num_list
#[1,3,4,8]

num_list.reverse()
#[8,4,3,1]
Dictionaries

Dictionaries are unordered mappings for storing objects, as such they cannot be sorted. They use key-value pairs to grab objects without needing to know an index location. Dictionaires use curly braces and colons to signify the keys and their associated values.{"key1":"value1","key2":"value2"}.

Creating Dictionaries
my_dict = {"key1":"value1","key2":"value2"}

my_dict
#{"key1":"value1","key2":"value2"}

my_dict["key1"]
#"value2"

prices_lookup = {"apple":1.99,"oranges":1.50,"milk":2.50}
prices_lookup["apple"]
#1.99

d = {"k1":123,"k2":[9,8,7],"k3":{"inside_key":100}}

d["k2]
#[9,8,7]

d["k2][2]
#7

d["k3"]
#{"inside_key":100}

d["k3"]["inside_key]
#100

d= {"key1":["a","b","c"]}

my_list = d["key1"]

letter = my_list[2]
letter.upper()
#C

# Can do all operations in one step
d["key1"][2].upper()
Modifying Dictionaries
d = {"k1":100,"k2":200}
d["k3"] = 300
#{"k1":100,"k2":200,"k3":300}

d["k1] = "New Value"
#{"k1":"New Value,"k2":200,"k3":300}
Reviewing Dictionaries
d = {"k1":100,"k2":200}

d.keys()
#["k1","k2"]

d.values()
#[100,200]

d.items()

[("k1",100),("k2,200)]
Tuples

Tuples are very similar to lists. However they are immutible, therefore once inside a tuple it cannot be reassigned. Tuples use parenthesis: (1,2,3).

t = (1,2,3)
type(t)
#tuple

len(t)
#3

t = ("one", 2, 3)

t[0]
#"one"

t[-1]
#3

t = ("a","a",b")
t.count("a")
#count

'''Returns first occurance of "a"'''
t.index("a")
#0

t.index("b")
#2
Tuples Immutability
my_list = [1,2,3]
my_list[0] = "NEW"
#["NEW",2,3]

t = (1,2,3)
t[0] = "New"
#TypeError
Sets

Sets are unordered collections of unique elements. There can only be one representation of the same object.

my_set = set()

my_set.add(1)
#{1}

my_set.add(2)
#{1,2}

my_set.add(2)
#{1,2}

my_list = [1,2,2,1,2,3,4,4,4,5,3,2,1,2]
set(mylist)
#{1,2,3,4,5}
'''sets are not ordered'''
Booleans

Booleans are True or False operators.

1 > 2
#False

1 == 1
#True

'''None can be used as a placeholder'''
b = None
type(b)
#None

Comparison Operators

Operator Description Example
== Returns true if values are equal (a==b) is not true
!= Returns true is values are not equal (a!=b) is true
> Returns true is the value on the left is greater than the right (2 > 1) is true
< Returns true is the value on the left is less than the right (2 < 1) is not true
>= Returns true is the value on the left is greater or equal to the right (1 >= 2) is not true
<= Returns true is the value on the left is less than or equal to the right (1 <= 2) is true
2 == 2
#True

"Hello" == "Bye"
#False
"Bye" == "bye"
#False

"2" == 2
#False

2.0 == 2
#True

3 != 3
#False

4 != 5
#True
Chaining Comparison Operators/Logical Operators

Logical operators (and/or/not) can be used to combine comparisons

1 < 2 < 3
#True
1 < 2 and 2 < 3
#True

1 < 2 > 3
#False
1 < 2 and 2 > 3
#False

1 == 1 or 2 == 2
#True

100 == 1 or 2 == 2
#True

1 == 1
#True

not (1 == 1)
#False
'''Returns the opposite boolean'''

not 400 > 5000
True

Python Statements

if, elif and else Statements

When programming we sometimes only want certain sections of code to execute when a particular condition has been met. These can be done with the if,elif and else. Python uses colons and indentation (4 spaces).

if some_condition:
    # execute some code
elif some_other_condition:
    # do something different
else:
    # do something else

An example can be found below:

name = "Rikki"

if name == "Rikki":
    print("Hello Rikki!")
elif name == "Jocelyn":
    print("Hello Jocelyn")
else:
    print("What is your name?")
for Loops

for loops allow you to iterate over every element in an object. Such as an element in a list or character in a string.

Iterating Through Lists
my_iterable = [1,2,3]

for item_name in my_iterable:
    print(item_name)
#1
#2
#3

Some examples can be seen below:

my_list = [1,2,3,4,5,6,7,8,9,10]

for num in my_list:
    print(num)
#prints 1-10
for num in my_list:
    if num % 2 == 0:
        print(num)
#prints even numbers

list_sum = 0

for num in my_list:
    list_sum += num
    
print(list_sum)
#55
Iterating Through Strings
for letter in "Hello World:
    print(letter)

#Prints each character in the string "Hello World"

for _ in "Hello World:
    print("Cool!")

#Prints Cool the same number of times there are character in the string "Hello World"
Tuple Unpacking
tuple = (1,2,3)

for item in tup:
    print(item)
#Prints 1-3

my_list = [(1,2),(3,4),(5,6),(7,8)]
len(my_list)
#4

for item in my_list:
    print(item)
'''
(1,2)
(3,4)
(5,6)
(7,8)
'''

for (a,b) in my_list:
    print(a)
    print(b)
'''
1
2
3
4
5
6
7
8
'''

my_list = [(1,2,3),(4,5,6),(7,8,9)]

for a,b,c in my_list:
    print (b)
'''
2
5
8
'''
Iterating Through Dictionaries
d = {"k1":1,"k2":2,"k3":3}
for item in d:
    print (item)
'''
k1
k2
k3
'''

for item in d.items():
    print (item)
'''
("k1",1)
("k2",2)
("k3",3)

for key,value in d.items():
    print (value)
'''
1
2
3
'''  
while Loops

while loops continue to execute a block of code while a condition remains True.

while some_boolean_codition:
    #do something
else:
    #do something else

Some more examples can be seen below:

x = 0

while x < 5:
   print(f"The current value of x is {x}")
   x += 1
else:
    print("X is not less than 5")
'''
The current value of x is 0
The current value of x is 1
The current value of x is 2
The current value of x is 3
The current value of x is 4
X is not less than 5
'''
break, continue and pass

The break, continue and pass keywords add additional functionality for loop use cases

  • break: Breaks out of the current closest enclosing loop.
  • continue: Goes to the top of the closest enclosing loop.
  • pass: Does nothing.
break
for letter in my_string:
    if letter == "i":
        break
    print(letter)
#R

x = 0

while x < 5:
    if x == 2:
    break
    print(x)
    x += 1
    
'''
0
1
'''
continue
my_string = "Rikki"

for letter in my_string:
    if letter == "i":
        continue
    print(letter)
'''
R
k
k
'''
pass
x = [1,2,3]

for item in x:
    #Any typical comment
# Results in an "EOF while parsing error"

for item in x:
    pass
# Runs without an error
Useful Operators
range
for num in range (10):
    print(num)
#prints 0-9

for num in range (3,10):
    print(num)
#prints 3-9

for num in range (0,11),2:
    print(num)
#prints even numbers from 0-10

my_list = list(range(0,11,2))
#my_list contains even numbers from 0-10
enumerate
index_count = 0

for letter in "abcde":
    print(f"At index {index_count} the letter is {letter}"
    index_count += 1

index_count = 0
word = "abcde"

for letter in word:
    print(word[index_count])
    index_count += 1
'''
a
b
c
d
e
'''

for item in enumerate(word):
    print(item)
'''
(0,"a")
(1,"b")
(2,"c")
(3,"d")
(4,"e")
'''
for index,letter in enumerate(word):
    print(index)
    print(letter)
    print("\n")
'''
0
a

1
b

2
c

3
d

4
e
zip
my_list1 = [1,2,3]
my_list2 = ["a","b","c"]

for item in zip(my_list1,my_list2):
    print(item)
'''
(1, "a")
(2, "b")
(3, "c")
'''

my_list3 = [100,200,300]

for item in zip(my_list1,my_list2,my_list3):
    print(item)
'''
(1, "a", 100)
(2, "b", 200)
(3, "c", 300)
'''

my_list1 = [1,2,3,4,5,6]
for item in zip(my_list1,my_list2,my_list3):
    print(item)
'''
(1, "a", 100)
(2, "b", 200)
(3, "c", 300)
'''
#Zips to the length of the shortest list

list(zip(my_list1,my_list2)
#[(1, "a"),(2, "b"),(3, "c")]
in
"x" in [1,2,3]
False

"x" in ["x","y","z"]
#True

"a" in "a world"
#True

"mykey" in {"mykey1":345,"mykey2":678}
#True

d = {"mykey1":345,"mykey2":678}

345 in d.values()
#True

345 in d.keys()
#True
Mathematical Functions
my_list [10,20,30,40,500]

min(my_list)
#10

max(my_List)
#100

Other libraries can be imported:

from random import shuffle

my_list = [1,2,3,4,5,6,7,8,9,10]
shuffle(my_list)

my_list
#[3,1,2,6,5,4,8,10,9,7]

from random import randint

randint(0,100)
#79

randint(0,100)
#99

my_num = rand(0,10)
input
result = input("Enter a number")
#Always accepts results as a string

float(result)
int(result)

result = int(input("Enter a number"))
List Comprehensions

A unique way to quickly create lists. If a list is being created with a loop statement and append(), list comprehensions are a good alternative.

my_string = "hello"

my_list = []

for letter in my_string:
    my_list.append(letter)

my_list
#["h","e","l","l","0"]

my_list = [letter for letter in my_string]

my_list = [x for x in "word"]
#["w","o","r","d"]

my_list = [num for num in range(0,11)]
#[0,1,2,3,4,5,6,7,8,9,10]

my_list = [num**2 for num in range(0,11)]
#[0,1,4,9,16,25,36,49,64,81,100]

my_list = [x for x in range(0,11) if x%2 == 0]
#[0,2,4,6,8,10]

celcius = [0,10,20,34.5]

fahrenheit = [( (9/5)*temp + 32) for temp in celcius]

fahrenheit
#[32.0,50.0,68.0,94.1]

Methods & Functions

Methods

Methods are built into objects

my_list = [1,2,3]

my_list.append(4)

my_list.pop()

my_list

You can often create the object place a "." and then press tab to see all available methods. Another way is to use the built in help function.

my_list = [1,2,3]

help(my_list)

help(my_list.insert) 
Functions

Functions allow blocks of code to be executed without needing to rewrite it and can be defined using the def keyword.

def name_of_function(name):
    '''
    Docstring explaining function
    '''
    print(f"Hello {name}")

name_of_function("Rikki")
#Hello Rikki

Typically the return keyword is used to send back the result of the function instead of printing it out. This allows the output of the function to be assigned to a new variable.

def add_function(num1,num2):
    return num1 + num2
    
result = add_function(1,2)
print(result)
#3
Default Values
def say_hello(name = "Default"):
    print(f"Hello {name}")
    
say_hello()
#Hello Default
Functions With Logic
def even_check(number):
    return number % 2 == 0

even_check(10)
#True

even_check(21)
#false

def check_even_list(num_list):
    '''
    Return true if any number is even inside a list
    '''
    for number in num_list:
        if number % 2 == 0:
            return True
        else:
            pass
    return False

check_even_list([1,3,5)]
#False
check_even_list([2,4,5])
#True
def check_even_list(num_list):
    '''
    Returns even numbers in a list
    '''
    even_numbers = []
    
    for number in num_list:
        if number % 2 == 0:
            even_numbers.append(number)
        else:
            pass
    return even_numbers
Tuple Unpacking With Functions
stock_prices = [("Apple",200),("Google",400),("Microsoft",100)]

for stock,price in stock_prices:
    print(price + (0.1*price))
'''
220.0
440.0
110.0
'''

work_hours = [("Abby",40),("Billy",45),("Cassie",39)]

def employee_check(work_hours):
    current_max = 0
    employee_of_month = ""
    
    for employee,hours in work_hours:
        if hours > current_max:
            current_max = hours
            employee_of_month = employee
        else:
            pass
    return (employee_of_month,current_max)
    
name,hours = emmployee_check(work_hours)

name
#Billy

hours
#45
Interactions Between Functions

Typically outputs from one function are used as an input for another. Functions were used to design the game 3 cup monte which can be found here

*args and ** kwargs in Functions

*args and ** kwargs stand for arguments and keyword arguments and are used when passing an arbitrary number of arguments into a function.

*args

Return a tuple

def my_func(a,b):
    #Returns 5% of the sum of a and b
    
    return sum((a,b)) * 0.05

my_func(40,60)
#5
#Only takes 2 argumnets

def my_func(*args):
    return sum(args) * 0.05

my_func(40,60,40,20,50,70,80)

args is an arbitrary word and does not have to be used. However, it is convention but determining factor is the star.

**kwargs

return a dictionary

def my_func(**kwargs):
    if "fruit" in kwargs:
        print(f"My fruit of choice is {kwargs['fruit']}")
    else:
        print("I did not find any fruit here")
        
my_func(fruit = "apple",veggie = "lettuce")
My fruit of choice is apple

kargs is an arbitrary word and does not have to be used. However, it is convention but determining factor is the double star.

*args and * kwargs
def my_func(*args,**kwargs):
    print(f"I would like {args[0]} {kwargs['food']}")

my_func(10,20,30,fruit = "orange", food = "eggs", animal = "dog")
#I would like 10 eggs

Lambda Expressions, Maps & Filter

map

Applies a function to each element in an iterable e.g list

def square(num):
     return num**2

my_nums = [1,2,3,4,5]

for item in map(square,ny_nums):
    print(item)
'''
1
4
9
16
25
'''

new_list =list(map(square,my_nums))
new_list
#[1, 4, 9, 16, 25]
def splicer(my_string):
    if len(my_string) % 2 == 0:
        return "EVEN"
    else:
        return my_string[0]
        
names = ["Rikki","George", "James"]

new_list = list(map(splicer,names))

print(new_list)
#['R', 'EVEN', 'J']
filter

Filter by a function that returns either true or false

def check_even(num):
    return num % 2 == 0

my_nums = [1,2,3,4,5,6]

new_list = list(filter(check_even,my_nums))
#[2,4,6]
Lambda Expressions
square = lambda num: num ** 2

square(5)
#25
Lambda Expressions With maps
my_nums = [1,2,3,4,5]
new_list = list(map(lambda num: num**2, my_nums))
new_list
#[1, 4, 9, 16, 25]

names = ["Rikki","George", "James"]
new_list = list(map(lambda name:name[0],names))
#["R","G","J"]
new_list = list(map(lambda name:name[::-1],names))
#["ikkiR","egroeG","semaJ"]
Lambda Expressions With filters
my_nums = [1,2,3,4,5]
new_list = list(filter(lambda num: num % 2 == 0, my_nums))
[2,4]

Object Orientated Programming

Object Orientated Programming (OOP) allows you to create your own objects that have methods and attributes. Methods act as functions that use information about the object to return results or modify the current object. Examples include, appending to a list or counting occurences using a tuple.

In general, OOP allows the production of code that is repeatable and organised. The convention is to use CamelCasing.

class NameOfClass():

    def __init__(self,param1,param2):
        self.param1 = param1
        self.param2 = param2

    def some_method(self):
        # perform an action
        print(self.param1)
Attributes and class
class Dog():
    def __init__(self,breed,name,spots):
        self.breed = breed
        self.name = name
        self.spots = spots
        
my_dog = Dog(breed = "Lab", name = "Flapjack", spots = False)

my_dog.breed
#Lab
Class Object Attributes
class Dog():

    #Class Object Attributes are the same for any instance of a class
    species = "mammal"
    
    def __init__(self,breed,name,spots):
        self.breed = breed
        self.name = name
        self.spots = spots

my_dog = Dog(breed = "Lab", name = "Flapjack", spots = False)

my_dog.species
#mammal
Methods
class Dog():

    #Class Object Attributes are the same for any instance of a class
    species = "mammal"
    
    def __init__(self,breed,name):
        self.breed = breed
        self.name = name
        
    #Operations/Actions ---> Methods
    
    def bark(self,number):
        print(f"Woof! my name is {self.name} and the number is {number}")

my_dog = Dog("Lab","Flapjack")

my_dog.bark(7)
Woof! my name is Flapjack and the number is 7
class Circle():

    pi = 3.14
    
    def __init__(self,radius = 1):
        self.radius = radius
        self.area = radius*radius*Circle.pi
        
    def get_circumference(self):
        return self.radius * 2 * self.pi

my_circle = Circle()
my_circle.get_circumference
#
Inheritance

Inheritance works by creating classes using existing classes.

class Animal():
    
    def __init__(self):
        print("Animal created")
        
    def who_am_i(self):
        print("I am an animal")
        
    def eat(self):
        print("I am eating")

my_animal = Animal()
#Animal created

class Dog(Animal):
    
    def __init__(self):
        Animal.__init__(self)
        print("Dog created")

    def who_am_i(self):
        print("I am a dog!")
        
    def bark(self):
        print("WOOF!)
        
my_dog.eat()
#I am eating
my_dog.who_am_i()
#I am a dog
Polymorphism

Polymorphism refers to different object classes using the same method name and can be called from the same place depending on the arguments passed in.

class Dog():
    
    def __init__(self,name):
        self.name = name
        
    def speak(self):
        return self.name + " says woof!"

class Cat():
    
    def __init__(self,name):
        self.name = name
        
    def speak(self):
        return self.name + " says meow!"

niko = Dog("Niko")
felix = Cat("Felix")

print(niko.speak())
print(felix.speak())


for pet in [niko,felix]:
    print(type(pet))
    print(pet.speak())
'''
<class '__main__.Dog'>
Niko says woof!
<class '__main__.Cat'>
Felix says meow!
'''    

def pet_speak(pet):
    print(pet.speak())
    
pet_speak(nico)
pet_speak(felix)
'''
Niko says woof!
Felix says meow!
'''
Abstract Classes
class Animal():

    def __init__(self,name):
        self.name = name
        
    def speak(self):
        raise NotImplementedError("Subclass must implement this abstract method")
        
class Dog(Animal):
    
    def speak(self):
        return self.name + " says woof!"

class Cat(Animal):
    
    def speak(self):
        return self.name + " says meow!"
        
fido = Dog("Fido")
shiba = Cat("Shiba")

print(fido.speak())
print(shiba.speak())
Special/Magic/Dunder Method
print/str
class Book():

    def __init__(self,title,author,pages):
    
        self.title = title
        self.author = author
        self.pages = pages
    
    def __str__(self):
        return f"{self.title} by {self.author}"
    
b = Book("Python Rocks","Rikki",200)
print(b)
#Python Rocks by Rikki
len
class Book():

    def __init__(self,title,author,pages):
    
        self.title = title
        self.author = author
        self.pages = pages
    
    def __len__(self):
        return self.pages
    
b = Book("Python Rocks","Rikki",200)
len(b)
#200
del
class Book():

    def __init__(self,title,author,pages):
    
        self.title = title
        self.author = author
        self.pages = pages
    
    def __del__(self):
        print("A book object has been deleted")
    
b = Book("Python Rocks","Rikki",200)

del b
#A book object has been deleted