<jupyter_start><jupyter_text>Welcome to the Python Beginner's Workshop IntroductionMy name is <NAME>, I'm a software developer at Tavan Systems, Tavan Systems is a software and business solutions company based in Ottawa, ON. Although, I work as a software developer, I studied Mathematics at uOttawa. I held a few software and web development positions at multiple organizations including the Government of Canada and the Bank of Canada. I have also served as a Teachers Assistant for a coding course through Carleton University and TrilogyEd.Which should serve as a testament that you need not a CS or SoftEng degree to author good code. Anyone of you can become a skilled programmer, all it takes is time and persistence.The purpose of this workshop is to get you familiar with programming. We chose Python because it's one of the easiest  Object Oriented Programming (OOP) languages, its use cases are limitless, it has many resources online, it's very popular among the software development community, and starting with Python will give you enough foundations to shift to another programming language.With Python you can build a website, write automation scripts to automate your daily life, process some data using data science techniques, run a machine learning algorithm, build mobile and desktop apps, build robots, and a thousand other use cases.  Are We Going To Cover All of That? The answer is no. We will cover the underlying fundemental methods and tools of Python such as objects, loops etc. With these methods and tools, you'll have enough knowledge to enter other niched topics such as ML and Web Development. Keep in mind, whether you're building a website or running a machine learning algorithm, you'll still be using these fundemental tools and methods. When you choose a programming niche, you're extending on these methods with new methods and techinques specific to that niche. For example, if you want to use Python for machine learning, you'll have to learn how to use the Keras or Tensor Flow extension. But you'll still be defining variables and using objects i.e. the material we will cover in this workshop. ResourcesI based this workshop on the W3Schools Python Tutorial, because I believe its very beginner friendly, and to be frank, it's where I started with Python. However, it is not the exact same as I think some parts could be explained better, some parts can be omitted and some parts should have been added. Feel free to go through their tutorial [here](https://w3schools.com/python). Let's Get Started!Any questions before we start? Anyone need to run to the washroom? No? Well alright then!*Windows users:* To find out whether your system is a 32/64 Bit. Go to `Control Panel > System and Security > System` What you will need1. An Integrated Development Environment (IDE): Please download VS Code [here](https://code.visualstudio.com/download).    * Add the code runner extension.    2. Python 3 or larger: Download it [here](https://www.python.org/downloads/).    * *Windows Users:*  Don't forget to select "ADD TO PATH".3. Download the course content [here](https://github.com/abdu997/python-workshop).    * Click "Code"     * Then click "Download Zip"    4. For Windows users, download Git Bash [here](https://git-scm.com/downloads). Our FlowThis is how the workshop will work. 1. I'll explain a concept or method. 2. I'll show you an example. 3. You'll complete a group activity.4. I'll explain the solution.4. Repeat.  Getting familiar with the Bash TerminalWindows users open your Git Bash, Mac users open your Terminal app. Run the following command```sh$ python --version```This should return "Python 3.x.x" or similar. If it does, you may run your scripts using the "python" If returns "Python 2.x.x" or similar that means you're default python is version 2. For this workshop, we will be using Python 3, so you'll have to run the following command.```sh$ python3 --version```If this worked, you will have to run all of your scripts using "python3".  01 Let's Run A ScriptThe first function we will cover will be the `print()` function. This function will print whatever message we place in it, when the script runs.<jupyter_code>print("Hello, World!")<jupyter_output>Hello, World!<jupyter_text>To run a python script, you will have to create a file that bears the extension `.py`, so your file name will be `filename.py`. You can then write your python code in the file. To run the file, open your Bash Terminal. You may open it in the VS code by clicking `Terminal` in the top bar, then clicking `New Terminal`.If you're a Windows user, don't forget to switch from `Command Terminal` to `Git Bash` or `Bash`.![Command line breakdown](Images/terminal-line.png)The image above offers a breakdown of a typical command line to run a python script. What if the terminal isn't on the folder where my script is?Then you may change to the folder by running a `cd` Change Directory```sh $ cd toTheFolder```To move back ```sh $ cd ..```  Activity 01Navigate to the Activities folder and open the `01-print.py`. Print whatever message you would like. And run the script.  02 Data Types| Data Type 	| Name       	| Definition                                                                                                   	| Example                                          	||-----------	|------------	|--------------------------------------------------------------------------------------------------------------	|--------------------------------------------------	|| `str`     	| String     	| Text type, always wrapped in quotation marks                                                                 	| `"Hello"`                                        	|| `int`     	| Integer    	| Whole numbers, NOT wrapped in quotation marks                                                                	| `313`                                            	|| `float`   	| Float      	| Decimal numbers, NOT wrapped in quotation marks                                                              	| `21.43`                                          	|| `complex` 	| Complex    	| Complex numbers                                                                                              	| `3 + 2j`                                         	|| `list`    	| List       	| A list of elements. The elements can be other data types.                                                    	| `["Mark", "Mike", "Julie"]`                      	|| `tuple`   	| Tuple      	| A tuple is a collection which is ordered and unchangeable. In Python tuples are written with round brackets. 	| `("Mark", "Mike", "Julie")`                     	|| `dict`    	| Dictionary 	| An associative set of data. All data is in a `key: value` pair.                                              	| `{ 'firstName': "Abdul", 'lastName': "Amoud" }` 	|| `bool`    	| Boolean    	| `True` or `False`                                                                                            	| `True`                                           	|And many more! But these are the most important ones, and they will be the ones we cover in this workshop. Activity 02Navigate to the Activities folder and open the `01-datatypes.py`. Print a string, an integer, a list, and a dictionary.BONUS: Print the rest of the Data Types we covered.  03 Type CastingThere may be times when you want to specify a type on to a variable. This can be done with casting. Python is an object-orientated language, and as such it uses classes to define data types, including its primitive types.Casting in python is therefore done using constructor functions:int() - constructs an integer number from an integer literal, a float literal (by rounding down to the previous whole number), or a string literal (providing the string represents a whole number)float() - constructs a float number from an integer literal, a float literal or a string literal (providing the string represents a float or an integer)str() - constructs a string from a wide variety of data types, including strings, integer literals and float literals [1]bool() - contructs a boolean from a data type, converts a truthy data type to `True` and falsey data types to `False`. Truthy values are non empty values. Falsey values are empty values such as an empty string `""` or `0` or failed conditions `2 < 1`.<jupyter_code>int(1)      # will be 1
int(2.8)    # will be 2
int("3")    # will be 3

float(1)    # will be 1.0
float(2.8)  # will be 2.8
float("3")  # will be 3.0
float("4.2")# w will be 4.2

str("s1")   # will be 's1'
str(2)      # will be '2'
str(3.0)    # will be '3.0'

bool("hello") # will be True
bool(0)   # will be False
bool("False") # what will this be?
# To know which type is a object we use the type() function
type("hello")<jupyter_output><empty_output><jupyter_text>Activity 03Navigate to the Activities folder and open the `01-casting.py`. Print a casted string, a casted integer, and a casted float  04 VariablesVariables are containers for storing data values. we use variables to store a value for later use. [2]<jupyter_code>#Legal variable names:
firstname = "John"
first_name = "John"
_first_name = "John"
firstName = "John"
FIRSTNAME = "John"
firstname1 = "John"

#Illegal variable names:
2firstname = "John"
first-name = "John"
first name = "John"
citrus, stone_fruit, berry = "Orange", "Mango", "Cherry"
fruit = citrus  = "Orange"

patient_name = "Mark"
patient_name = "Gene"
# What is the patient's name?<jupyter_output><empty_output><jupyter_text>Activity 04Navigate to the Activities folder and open the `04-variables.py`. Store the patient's vitals in aptly named variable.Body Temperature 37, Pulse Rate 154, Respiration Rate 13, Blood Pressure 120.  05 User InputsPython's user `input()` function is used to prompt the user for scripts inputs. Let's say your code runs on some changing variables, you may use `input()` to fetch the values of these variables.<jupyter_code>username = input("What is your name?")<jupyter_output><empty_output><jupyter_text>Activity 05Open the `05-userinput.py` script in the `Activities` folder. Write code that requests and prints a patient's name and their vitals.  06 String FormatingBasically, we will be learning how to glue texts together. We will do so using the `.format()` function.<jupyter_code>driver_name = "<NAME>"
age = 35

message = "The driver's name is {0}, and he is {1} years old."
message.format(driver_name, age)

# We can also do it this way
message = "The driver's name is {driver_name}, and he is {age} years old."
message.format(driver_name = "<NAME>" , age = 24)<jupyter_output><empty_output><jupyter_text>Activity 06Open the 06-stringformatting.py script in the Activities folder. Concatenate a message to your best friend using `.format()`.  07 Operators and ConditionsOperators are symbols that we use to evaluate a expression. Below is a list of Python operators. Arithematic Operators| Operator 	| Function       	      | Example  	||----------	|------------------	      |----------	|| `+`      	| Addition       	      | `1 + 1` = `2`  	|| `-`      	| Subtraction    	      | `3 - 1` = `2`  	|| `*`      	| Multiplication 	      | `2 * 2` = `4`  	|| `/`      	| Division       	      | `6 / 2` = `3`  	|| `//`      | Division and round down | `7 // 2` = `3`  	|| `**`     	| Exponential    	      | `2 ** 3` 	| Comparison OperatorsComparison operators return a boolean as a result of the evaluation.| Operator 	| Function                  	| Example  	||----------	|---------------------------	|----------	|| `==`     	| Exact equality            	| `1 == 1` 	|| `!=`     	| Inequality                	| `3 != 1` 	|| `>`      	| Larger than               	| `3 > 2`  	|| `<`      	| Smaller than              	| `2 < 6`  	|| `>=`     	| Larger than or equal too  	| `4 >= 3` 	|| `<=`     	| Smaller than or equal too 	| `2 <= 2` 	| Logical Operators| Operator 	| Function                                      	| Example            	||----------	|-----------------------------------------------	|--------------------	|| `and`    	| Returns True if both statements are true      	| `1 == 1 and 2 < 3` 	|| `or`     	| Returns True if one of the statements is true 	| `3 == 1 or 1 != 2` 	|| `not`    	| Returns True if value is falsey                                   	| `not 1 == 2`       	| If StatementsNow that you know how conditions can be set, now its time to use them in if statements. This is how a typical if statement looks like.<jupyter_code>if 3 < 5:
    print("3 is in fact, smaller than 5, shocker!")
if 9 + 10 == 21:
    print("You smart")
else:
    print("Nine plus ten is not 21")
# In fact you can write if statements may different ways
if 3 < 2:
    print("3 is smaller than 2")
elif 1 + 1 == 2:
    print("1 plus 1 is 2")
else:
    print("I really need to learn numbers again")<jupyter_output><empty_output><jupyter_text>Activity 07Navigate to `07-conditionals.py` and solve the practice question.  08 Lists and DictionariesWe've seen these before during section 02 Data Types, but let's dig a little deeper. Lists and dictionaries are types of data structures.<jupyter_code>favouriteCats = ["Fluffy", "Snowball", "Mr. Whiskers"]<jupyter_output><empty_output><jupyter_text>Lists in Python and many other programming languages are indexed. The first index is 0<jupyter_code>favouriteCats[0] # Prints Fluffy
favouriteCats[1] # Prints Snowball
favouriteCats[2] # Prints Mr. Whiskers
favouriteCats[3] # IndexError: list index out of range, since there isn't a fourth element in the list<jupyter_output><empty_output><jupyter_text>You can add to a list by appending an element to it by using .append()<jupyter_code>favouriteCats.append("Simba")<jupyter_output><empty_output><jupyter_text>You can reset the value of an index.<jupyter_code>favouriteCats[1] = "Fluff"
cat = {
    'name': 'Fluffy',
    'age': 15,
    'parents': ["<NAME>", "<NAME>"],
    'home': {
        'city': 'Ottawa',
        'country': 'Canada'
    }
}<jupyter_output><empty_output><jupyter_text>To access the values we do the following<jupyter_code>cat['name'] # <NAME>
cat['age'] # 49
cat['parents'] # ["<NAME>", "<NAME>"]
cat['parents'][1] # <NAME>
cat['home']['city'] # Ottawa<jupyter_output><empty_output><jupyter_text>You can change a property value by equating it to a new value<jupyter_code>cat['home']['city'] = "Toronto"<jupyter_output><empty_output><jupyter_text>You can set a new property with a new value by doing the following<jupyter_code>cat['breed'] = "Tabby"<jupyter_output><empty_output><jupyter_text>We can even have a lists of dicts!! And you can treat them the same. This format is usually referred to as `JSON`.<jupyter_code>cats = [
    {
        'name': 'Fluffy',
        'age': 15,
        'parents': ["<NAME>", "<NAME>"],
        'home': {
            'city': 'Ottawa',
            'country': 'Canada'
        }
    },
    {
        'name': 'Snowball',
        'age': 5,
        'parents': ["<NAME>", "Beyonce"],
        'home': {
            'city': 'Amsterdam',
            'country': 'Netherlands'
        }
    },
]<jupyter_output><empty_output><jupyter_text>Activity 08Navigate to `08-listsanddicts.py` and solve the practice question.  09 For LoopsLoops are blocks of code that run on each element of a list. If a list has 10 elements, the block of code will run 10 times.<jupyter_code>list = ["Oh Hi Mark", "You can't handle the truth.", "Wait, that's illegal!"]
for element in list:
    # Run some code on element
    print(element)<jupyter_output>Oh Hi Mark
You can't handle the truth.
Wait, that's illegal!<jupyter_text>Let's loop through a JSON array.<jupyter_code>cats = [
    {
        'name': 'Fluffy',
        'age': 15,
        'parents': ["<NAME>", "<NAME>"],
        'home': {
            'city': 'Ottawa',
            'country': 'Canada'
        }
    },
    {
        'name': 'Snowball',
        'age': 5,
        'parents': ["<NAME>", "Beyonce"],
        'home': {
            'city': 'Amsterdam',
            'country': 'Netherlands'
        }
    }
]

for cat in cats:
    print(cat['name'])<jupyter_output>Fluffy
Snowball<jupyter_text>Activity 09Navigate to `09-forloops.py` and solve the practice question.  10 While LoopsAs you can recall, a for loop runs a block of code `n` times, for an `n` sized array/list. `while` loops run a block of code as long as a condition is true. Think of it as an `if` statement that continues on running over and over again as long as the condition is true.<jupyter_code>index = 0
while index < 3:
    print('index is now', index)
    index = index + 1<jupyter_output>index is now 0
index is now 1
index is now 2<jupyter_text>Another Example<jupyter_code>run = "yes"
users = []
while run == "yes":
    newuser = input("What's the name of the new user: ")
    users.append(newuser)
    run = input("Do you want to add another user? (yes) ")
print(users)<jupyter_output>['']<jupyter_text>Activity 10Navigate to `09-whileloops.py` and solve the practice question.  11 FunctionsYou may have noticed that when we write code in a script, all code runs when the script runs. What if we want to have some code we want to run by command, whenever we want, however many times we want?We can, by placing our code in a function using the `def` operator. Here's an example.<jupyter_code>def function_name():
    print("We called our first function!")<jupyter_output><empty_output><jupyter_text>Notice how nothing happens when we run the code above? That's because the function was never `called`. So let's call it!<jupyter_code>function_name()<jupyter_output>We called our first function!<jupyter_text>What if we want to pass values (`arguments`) to a function?<jupyter_code>def kinda_sus_generator(color):
    message = '{} kinda sus'.format(color)
    return message

kinda_sus_generator("Red")<jupyter_output><empty_output><jupyter_text>How about passing more than one argument?<jupyter_code>def vote_result_message(name, isImposter):
    if isImposter:
        return name + " was an imposter"
    else:
        return name + " was not an imposter"

# Arguments need to follow the order of the function declaration
vote_result_message("GangGang", False)
# We can also do it like this
vote_result_message(name = "Not An Imposter", isImposter = True)
# You can break the order if you declare what each argument is.
vote_result_message(isImposter = False, name = "Bruh")<jupyter_output><empty_output><jupyter_text>Abstraction<jupyter_code>lewis_temperature_F = 102
tommy_temperature_F = 98

# Let's convert the temperature to Celsius
lewis_temperature_C = ((lewis_temperature_F - 32) * 5) / 9
tommy_temperature_C = ((tommy_temperature_F - 32) * 5) / 9<jupyter_output><empty_output><jupyter_text>Notice how we are rewriting similar code multiple times? Seems tedious, so let's do some `abstraction`!<jupyter_code>def fahernheit_to_celsius(temperature_in_fahernheit):
    return ((temperature_in_fahernheit - 32) * 5) / 9

# Now back to our example
lewis_temperature_F = 102
tommy_temperature_F = 98

lewis_temperature_C = fahernheit_to_celsius(lewis_temperature_F) # Whatever the function returns is the value of the variable
tommy_temperature_C = fahernheit_to_celsius(tommy_temperature_F)<jupyter_output><empty_output><jupyter_text>Scoping<jupyter_code>x = 1
def add_to_x(y):
    # Notice how we can still use x even though it's outside the function?
    return x + y
add_to_x(2)
# But if we try to print y
y<jupyter_output><empty_output><jupyter_text>Activity 11Navigate to activity file `11-functions.py` and solve the problem.  12 Lambda FunctionsA lambda function is a small anonymous function. It can take any number of arguments, but can only have one expression. Think of it as a mini one-liner function.Let's use the previous fahernheit_to_celsius function as an example.<jupyter_code>fahernheit_to_celsius = lambda t: ((t - 32) * 5) / 9
fahernheit_to_celsius(32)<jupyter_output><empty_output><jupyter_text>Activity 12Navigate to activity file `12-lambda.py` and solve the problem.  13 ClassesA Class is like an object constructor, or a "blueprint" for creating objects. Classes can be used as a collection of related functions and variables. To create a class, use the keyword `class`:<jupyter_code># Notice how the classname is capitalized
class Math:
    def addition(x, y):
        return x + y
    def subtraction(x, y):
        return x - y
    def multiplication(x, y):
        return x * y
# To use a function in the class, first we have to create an instance of the class.
math = Math()
Math.addition(1, 2)<jupyter_output><empty_output><jupyter_text>Activity 13Navigate to activity file `13-classes.py` and solve the problem.  14 InstantiationRecall when we referred to class objects as blueprints? We can have a class with properties that persist throughout the runtime of the app. When we create an instance of the class, defining the class' properties, we are instantiating. We can have multiple different instances of a class. When a class has dyanmic properties, we usually refer to it as a dynamic object. Let's dig in to it.<jupyter_code># Recall our past STATIC class
class Math:
    def addition(x, y):
        return x + y
    def subtraction(x, y):
        return x - y
    def multiplication(x, y):
        return x * y<jupyter_output><empty_output><jupyter_text>Let's convert it to a dynamic classFirst we need to define `__init__()` function, other programming languages refer to this function as the `constructor` function. The first parameter the constructor function needs is the `self` parameter. The self parameter is a reference to the current instance of the class, and is used to access variables that belongs to the class.It does not have to be named self , you can call it whatever you like, but it has to be the first parameter of the class' functions.We use `self` to store the class' properties.<jupyter_code># Let's convert it to a dynamic class
class Math:
    def __init__(self, x, y):
        self.x = x
        self.y = y<jupyter_output><empty_output><jupyter_text>Class propertiesSince we are storing `x` and `y` in `self` as class properties, we don't have to take in the variables again to run the rest of the functions.<jupyter_code>class Math:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def addition(self):
        return self.x + self.y
    def subtraction(self):
        return self.x - self.y
    def multiplication(self):
        return self.x * self.y<jupyter_output><empty_output><jupyter_text>Let's Run It<jupyter_code>x_is_1_y_is_2 = Math(x = 1, y = 2)
x_is_1_y_is_2.addition()<jupyter_output><empty_output><jupyter_text>Doesn't Make Sense?Fear not, many of my students struggle with this concept. Let's cover another example.<jupyter_code>class Box:
    def __init__(self, name, color, width, length, height, mass):
        self.name = name
        self.color = color
        self.width = width
        self.length = length
        self.height = height
        self.mass = mass

    def volume(self):
        return self.width * self.length * self.height

    def density(self):
        return self.mass / self.volume()
xbox = Box(name = "XBox", color = "white", width = 15.1, length = 15.1, height = 30.1, mass = 4.25)

xbox.volume()
xbox.density()
xbox.name<jupyter_output><empty_output><jupyter_text>15 Modules ImportsComplex programs are comprised of multiple classes, functions and objects spanning multiple files. If you have an object in a separate file, how do you use it on the file you're working on? You can import objects from different files by using the `import` operator.<jupyter_code>import filename<jupyter_output><empty_output><jupyter_text>Aliases You may even import the file as a different name<jupyter_code>import filename as fn<jupyter_output><empty_output><jupyter_text>Activity 14Navigate to activity file `14-instantiation.py` and solve the problem.  Import FromWhat if the file has mutliple objects and you would like to import a specifi function. You would then use `import function from filename`<jupyter_code># Let's say this is a file called math.py
def addition(x, y):
    return x + y
def subtraction(x, y):
    return x - y
def multiplication(x, y):
    return x * y
# Importing the file
import math
math.addition(x = 1, y = 2)

# To import addition from math.py
import addition from math

# You may also mix and match with the as operator
import addition from math as add<jupyter_output><empty_output><jupyter_text>Activity 15Navigate to activity file `15-moduleimports.py` and solve the problem.  16 PipWe covered how to import modules we have written our selves in different files. But what if I tell you can import functions and objects from modules written by the helpful engineers of the world.We would have to use `pip`. `pip` is python's package installer and manager. They have a repository of free and open-source code that was authored by engineers all over the world. We use `pip` to install packages and modules from others, so that we wouldn't have to write functions from scratch on our own. It also helps us abstract some functionalities in our program. You may peruse pip packages at https://pypi.org/For instance there is a package called `numpy`. `numpy` is a statistical package for python. Installing From Pip.If you have been running your python scripts using the `python` handle, you can run your `pip` commands as such.```sh $ pip install numpy```If you have been running your python scripts using the `python3` handle, you can run your `pip` commands as such.```sh $ pip3 install numpy``` Using the package you've installed<jupyter_code>import numpy 

# We can then start using the functions that come with numpy, let's find a mean of a list.
mean = numpy.mean([1,3,6,6])
print(mean)<jupyter_output>4.0<jupyter_text>Activity 16Navigate to activity file `16-pip.py` and solve the problem.  17 Try ExceptNotice how when there is an error in our script, our program grinds to halt and an error message is printed out. What if we wanted to control what happens in the scenario where the program has erred? We can plan for this unfortunate outcome by using the `try` and `except` operators. Essentially, we are running a block of code within the `try` scope; if an error occurs from the block of the code, then we run the code in the `except` block as a contingency plan.<jupyter_code>try:
    print(variable_that_does_not_exist)
except:
    print("You tried to print a variable that does not exist")<jupyter_output>You tried to set an illegal variable<jupyter_text>Raising Our Own ErrorsWhat if we want to create our own errors? Then we can `raise Exception()` an error<jupyter_code>def adults_only(age):
    if age < 18:
        raise Exception("Too young!")
    else: 
        print("Let's Party!")

try:
    adults_only(16)
except:
    print("An error was raised")<jupyter_output>An error was raised
{'fraction_non_alphanumeric': 0.09851813240002978, 'fraction_numerical': 0.012584704743465635, 'mean_word_length': 3.1771384136858476, 'pattern_counts': {'":': 1, '<': 169, '<?xml version=': 0, '>': 165, 'https://': 6, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 48, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '38', 'dir': 'jupyter-structured-clean-dedup', 'id': '595836', 'license': 'MIT', 'n_tokens_mistral': 7934, 'n_tokens_neox': 7413, 'n_words': 3322, 'path': 'instructor-notes.ipynb', 'repo_name': 'abdu997/python-workshop', 'size': '26957'}