diff --git a/deloitte-python-1-aug-2022/README.md b/deloitte-python-1-aug-2022/README.md new file mode 100644 index 0000000..56c6a90 --- /dev/null +++ b/deloitte-python-1-aug-2022/README.md @@ -0,0 +1,23 @@ +# Girl Develop It Python 1 Class, Aug 2022 + +## Overview +This course is a special series customized for the Deloitte WinC (Women in Computing) group. It's based on the standard GDI Python 1 curriculum, but adjusted for the interests of the group and for alignment with [PCEP exam topics](https://pythoninstitute.org/pcep-exam-syllabus), as Deloitte offered participants the option to take the exam at no cost. + +This course covers the very basics of the Python programming language, including: +- Data types +- Expressions/operators +- Functions +- Loops +- Data structures (lists, tuples, dictionaries) + +This class series consists of 6 2-hr sessions: + +- [Class 1](https://github.com/lizkrznarich/gdi-python-1/tree/main/class1): Intro to Python +- [Class 2](https://github.com/lizkrznarich/gdi-python-1/tree/main/class2): Functions +- [Class 3](https://github.com/lizkrznarich/gdi-python-1/tree/main/class3): Conditionals +- [Class 4](https://github.com/lizkrznarich/gdi-python-1/tree/main/class4): Loops +- [Class 5](https://github.com/lizkrznarich/gdi-python-1/tree/main/class5): Lists +- [Class 6](https://github.com/lizkrznarich/gdi-python-1/tree/main/class6): Tuples & Dictionaries + +## Using slides +Slides are in HTML - access them at the links above, or download this repository to your computer and open the classX.html file inside each classX folder in a browser (ex: [class1/class1.html](https://github.com/lizkrznarich/gdi-python-1/blob/main/class1/class1.html)) diff --git a/deloitte-python-1-aug-2022/class1/class1.html b/deloitte-python-1-aug-2022/class1/class1.html new file mode 100644 index 0000000..be4b317 --- /dev/null +++ b/deloitte-python-1-aug-2022/class1/class1.html @@ -0,0 +1,807 @@ + + + + + + Welcome to Python + + + + + + + + +
+
+ +
+

Welcome to Python

+ +
+ Tips for navigating the slides: +
    +
  • Press O or Escape for overview mode.
  • +
  • Visit this link for a nice printable version
  • +
  • Press the copy icon on the upper right of code blocks to copy the code
  • +
+
+ + +
+ +
+

Welcome!

+

Girl Develop It is here to provide affordable and accessible programs to learn software through mentorship and hands-on instruction.

+ +

Classroom "rules":

+
    +
  • I am here for you!
  • +
  • Every question is important
  • +
  • Help each other
  • +
  • Have fun
  • +
+
+
+

Class Outline

+ +

This may change if we end up needing more or less time for certain topics.

+
    +
  • Class 1: Intro to Python +
  • Class 2: Functions +
  • Class 3: Conditionals +
  • Class 4: Loops +
  • Class 5: Lists +
  • Class 6: Tuples & dictionaries +
+
+
+

Class logistics

+ +
+
+

Introductions

+

Tell us about yourself:

+
    +
  • Name +
  • Pronouns +
  • Location +
  • Programming experience (if any, not required!) +
  • What interests you about Python? +
+
+ +
+

Today's topics

+ +
    +
  • What/why Python? +
  • Simple data types & values +
  • Names +
  • Expressions & operators +
  • Built-in functions +
  • Imports +
  • Built-in methods +
+
+ +
+

What is Python?

+
+ +
+

The Python language

+ +
    +
  • An "interpreted" general purpose programming language. +
    • Huh?? Runs through an interpreter application, as opposed to "compiled" languages, which are converted to machine code and run directly by a computer
    +
  • Can run on many systems: Unix, Windows, Mac. +
  • An easy-to-read syntax where whitespace is significant. +
  • Open source +
+
+ +
+
+

The Python language

+

Example (that you don't need to understand yet!):

+

+                    def add_numbers_between(start, end):
+                        sum = 0
+                        for n in range(start, end):
+                            sum += n
+                        return n
+
+                    add_numbers_between(5, 10)
+                    
+ +
+ +
+

Why Python?

+
+ +
+

Benefits

+ +

For learning:

+
    +
  • Python's syntax is considered easier to read and use than most languages. +
  • The language includes features of many different types of languages, + so you can learn concepts that translate to other languages + (functional programming, object-oriented programming, etc). +
+ +

For development:

+
    +
  • Python can be used for a wide range of applications (web, data science, graphics, games, language, etc) + thanks to the huge number of libraries and tutorials. +
+ + + +
+ +
+

Console applications

+ +

You can make entirely text-based console (command-line) applications/scripts. These are common for automating tedious/repetitive tasks.

+ + Screenshot of a console application + +
+ +
+

Desktop applications

+ +

+ Applications for non-technical users typically include a GUI (graphical user interface).

+ + Screenshot of a desktop GUI application + +
+ +
+

Web applications

+ +

Web apps are increasingly more popular than downloaded apps. + HTML/CSS/JS would be used for the frontend, but Python can be used for the backend + of a web application.

+ + Screenshot of a desktop GUI application + +
+ +
+

Data analysis notebook

+ +

Data analysts and data scientists often use notebooks, like Jupyter Notebooks to document and share + calculations and outputs.

+ + Screenshot of a Jupyter notebook with Python code + +
+
+

πŸ’¬ What's one thing you'd LOVE to make with Python?

+
+
+

Python setup

+
+ +
+

Coding Python locally

+ +

Usually, we would write Python code on our own computers using: +

+ +

(click the links above for setup info)

+
+ +
+

Coding Python on Repl.it

+ +

Installing/running Python on lots of different systems/versions is tricky.

+

In this class, we'll use Replit, an online editor.

+ +

+ https://repl.it/languages/python3 + +

+
+ +
+

Repl.it setup

+
    +
  • Create a Replit account +
  • Once you're logged in, create a new Python repl +
+ screenshot of repl +
+
+

print()

+

We use print() to tell Python what to output. This is very useful in debugging - ex, to see the value of a variable. +

+

+                    print("hello world!"
+                    
+
+
+

(simple) Data types & values

+
+ +
+

(simple) data types & values

+ +

Programs manipulate values.

+

Each value has a certain data type.

+ + + + + + + + + +
Data type + Example values +
Integers + 2 44 -3 +
Floats + 3.14 4.5 -2.0 +
Booleans + True False +
Strings + 'Β‘hola!' 'its python time!' +
+
+
+

Names

+
+ +
+ Name bound to value +

Names

+ +

In Python, objects have names. Different types of objects (variables, functions, etc) can have names. +

+
+

A variable is a name bound to a value using an assignment statement:

+ + + + +
x + = + 7 +
Name + + Value +
+ +
+
+

Names

+
+

The value can be any expression:

+ + + + +
x + = + 1 + 2 * 3 - 4 // 5 +
Name + + Expression +
+
+ +
+

It can also be a function:

+ + + +
x + = + add(1+2) +
Name + + Expression +
+
+ +
+
+

Name rules

+ +

Only certain character combinations are allowed:

+
    +
  • Must start with a letter or the underscore character
  • +
  • Cannot start with a number
  • +
  • Can only contain alpha-numeric characters and underscores (A-z, 0-9, and _ )
  • +
+ + + + + +
+

Allowed names

+
    +
  • banana_gram +
  • Bananagram +
  • _banana_gram +
+
+

Non-allowed names

+
    +
  • 1banana_gram +
  • banana-gram +
  • banana gram +
+
+

See more examples at W3Schools: https://www.w3schools.com/python/gloss_python_variable_names.asp

+
+ +
+

Name rules

+ +

Names are case sensitive.

+ +

If name is my_fav_hobby, the following are not equivalent:

+ +
    +
  • my_fav_hobbY +
  • My_fav_hobby +
  • MY_FAV_HOBBY +
  • myfavhobby +
+ +

Programming can help you develop an eye for these little details, + but software development tools will also help you find these issues.

+ +
+
+

Naming conventions for variables & functions

+
    +
  • Use a lowercase single letter (variables only), word, or words +
  • Separate words with underscores +
  • Make names meaningful, ex first_name rather than fn +
+

+

Examples

+
    +
  • m (variables only) +
  • hobby +
  • my_fav_hobby +
+ +

See more examples at Real Python: https://realpython.com/python-pep8/#naming-styles

+
+
+

Using names

+ +

A name can be referenced multiple times:

+ +

+                x = 10
+                y = 3
+
+                result1 = x * y
+                result2 = x + y
+                
+ +
+

A name that's bound to a data value is also known as a variable.

+ +

πŸ’¬ How many variables are in that code snippet?
+ 4 variables: x, y, result1, result2 +

+
+ +
+ +
+

Name rebinding

+ +

A name can only be bound to a single value.

+ +

+                my_name = 'Liz'
+
+                my_name = my_name + 'iz'
+                
+ +

πŸ’¬ Will that code error? If not, what will my_name store?
+ It will not error (similar code in other languages might, however). + The name my_name is now bound to the value 'Liziz'. +

+
+ +
+

Expressions & operators

+
+ +
+

Expressions (with operators)

+ +

An expression describes a computation and evaluates to a value.

+ +

Some expressions use operators:

+ +

+                    18 + 69
+                    
+ +

+                    6/23
+                    
+ +

+                    2 * 100
+                    
+ +

+                    2 ** 100
+                    
+ +

Let's try it in Repl! +

+
+
+

Mathematical operators

+ + + + + + + + + + + +
Operator + Name + Example +
+ + Addition + 1 + 2 = 3 +
- + Subtraction + 2 - 1 = 1 +
* + Multiplication + 2 * 3 = 6 +
/ + Division + 6 / 3 = 2 +
% + Modulus (divide & return the remainder) + 5 % 2 = 1 +
** + Exponentation (aka powers) + 2 ** 3 = 8 +
// + Floor division (divide & round down to the nearest integer) + 5 // 2 = 2 +
+
+
+

Built-in functions

+
+
+

Expressions (with function calls)

+ +

Many expressions use function calls:

+ +

+                    pow(2, 100)
+                    
+ +

+                    max(50, 300)
+                    
+ +

+                    min(-1, -300)
+                    
+

Learn more about built-in functions in the Python docs.

+ +

Let's try these in Repl! +

+
+ + +
+

Expressions (both ways)

+ +

Expressions with operators can also be expressed with function call notation:

+ +

+                    2 ** 100
+                    pow(2, 100)
+                    
+ +
+
+

Imports

+
+
+

Importing functions & modules

+ +

Some functions from the Python standard library are available by default. + Others are included with a basic Python installation, but need to be imported + into your current file before they can be used.

+ +

Import a single function from the Operator module :

+ +
+

+                    from operator import add
+
+                    18 + 69
+                    add(18, 69)
+                    
+
+ +
+
+

Importing functions & modules

+ +

Import the entire Operator module (all of its functions):

+ +
+

+                    import operator
+
+                    18 + 69
+                    add(18, 69)
+                    
+ +

+ Why would we import a single function vs an entire module? Some modules are big! You'll get better performance by importing only what you need. +

+
+ +
+
+

Nested expressions

+
+
+

Nested expressions

+ +

We can combine multiple expression inside one another. These are evaluated from the inside out.

+ + screenshot of expression tree +
+ +
+

Exercise: Expressions

+ +

Open Open the Class1Ex1OperatorExpressions repl. +

+

Let's work through these questions together!

+
+
+

Forking Replit files

+
    +
  1. Click the link to the Replit, ex https://replit.com/@lizkrznarich/Class1Ex1OperatorExpressions +
  2. Click Fork Replit
    + +
  3. Click Edit in workspace + +
+
+
+

Built-in methods

+
+
+

Built-in methods

+

Each Python data type has built-in capababilites that are specific to that data type. These are call built-in methods.

+

Built-in methods use a different syntax from the operators and functions we looked at in the last section:

+

+
+                        'blar'.upper()
+
+                        my_string = 'blar'
+                        my_string.upper()
+                        
+

Learn more about built-in String methods in the Python docs

+
+
+

String methods

+

The Python String data type comes with some handy built-in methods that can be used to manipulate bits of text.

+ + + + + + + + + + +
Function + Description +
.upper() + Returns a copy of the string with all characters converted to uppercase +
.lower() + Returns a copy of the string with all characters converted to lowercase +
.title() + Returns a titlecased version of the string where words start with an uppercase character and the remaining characters are lowercase +
.swapcase() + Returns a copy of the string with uppercase characters converted to lowercase and vice versa +
.strip() + Returns a copy of the string with the leading and trailing whitespace characters removed +
+

For the full list, see Python3 docs

+
+
+

Exercise: Manipulating strings

+ +

Open the Class1Ex2TextProcessing repl. Let's play with some strings!

+ +
+
+

How is it going?

+

Please fill out the feedback form to let me know how I can improve the class!

+

https://forms.gle/iENMqYvdahR9AP5UA

+
+ +
+
+ + + + + + + + + diff --git a/deloitte-python-1-aug-2022/class2/class2.html b/deloitte-python-1-aug-2022/class2/class2.html new file mode 100644 index 0000000..5056a3f --- /dev/null +++ b/deloitte-python-1-aug-2022/class2/class2.html @@ -0,0 +1,1032 @@ + + + + + + Functions + + + + + + + + +
+
+ +
+

Functions

+ +
+ Tips for navigating the slides: +
    +
  • Press O or Escape for overview mode.
  • +
  • Visit this link for a nice printable version
  • +
  • Press the copy icon on the upper right of code blocks to copy the code
  • +
+
+ + +
+ +
+

Class outline:

+
  • Review & questions +
  • Functions intro +
  • Defining functions +
  • Namespaces +
  • More functions tips +
  • Practice exercises + +
  • + +
    +

    Review

    +
    +
    +

    Data types & values

    + +

    Programs manipulate values.

    +

    Each value has a certain data type.

    + + + + + + + + + +
    Data type + Example values +
    Integers + 2 44 -3 +
    Floats + 3.14 4.5 -2.0 +
    Booleans + True False +
    Strings + 'Β‘hola!' 'its python time!' +
    +
    +
    +

    Expressions & operators

    + +

    Python evaluates expressions into values in one or more steps.

    + + + + + + + + +
    Expression + Value +
    'ahoy' + 'ahoy' +
    'a' + 'hoy' + 'ahoy' +
    7 / 2 + 3.5 +
    +
    +
    +

    Mathematical operators

    + + + + + + + + + + + +
    Operator + Name + Example +
    + + Addition + 1 + 2 = 3 +
    - + Subtraction + 2 - 1 = 1 +
    * + Multiplication + 2 * 3 = 6 +
    / + Division + 6 / 3 = 2 +
    % + Modulus (divide & return the remainder) + 5 % 2 = 1 +
    ** + Exponentation (aka powers) + 2 ** 3 = 8 +
    // + Floor division (divide & round down to the nearest integer) + 5 // 2 = 2 +
    +
    +
    + Name bound to value +

    Variables

    + +

    A name can be bound to a value. +

    +

    A name that's bound to a data value is also known as a variable.

    +
    +

    One way to bind a name is with an assignment statement:

    + + + + +
    x + = + 7 +
    Name + + Value +
    + +
    +

    The value can be any expression:

    + + + + +
    x + = + 1 + 2 * 3 - 4 // 5 +
    Name + + Expression +
    +
    +
    +
    +

    Naming conventions for variables & functions

    +
      +
    • Use a lowercase single letter (variables only), word, or words +
    • Separate words with underscores +
    • Make names meaningful, ex first_name rather than fn +
    +

    +

    Examples

    +
      +
    • m (variables only) +
    • hobby +
    • my_fav_hobby +
    + +

    See more examples at Real Python: https://realpython.com/python-pep8/#naming-styles

    +
    +
    +

    Built-in functions

    + +

    Python has lots of built-in functions. Built-in functions are not specific to a particular data type - they often work on multiple data types (but check the docs!)
    + Some examples are:

    + +
    
    +                    pow(2, 100)
    +                    
    + +
    
    +                    max(50, 300)
    +                    
    + +
    
    +                    min(-1, -300)
    +                    
    +
    +
    +

    Importing functions & modules

    + +

    Some functions from the Python standard library are available by default. + Others are included with a basic Python installation, but need to be imported + into your current file before they can be used.

    + +

    Import a single function from the Operator module :

    + +
    +
    
    +                    from operator import add
    +
    +                    18 + 69
    +                    add(18, 69)
    +                    
    +
    + +
    +
    +

    Debugging with print()

    +

    One of the most commonly-used built-in functions is print() +

    +

    We use print() to tell Python what to output to the console. This is very useful in debugging - ex, to see the value of a variable. +

    +
    
    +                    print("hello world")
    +                    x = 5
    +                    y = 10
    +                    print(x)
    +                    print(y)
    +                    print(x+y)
    +                    
    +
    +
    +

    Built-in methods

    + +

    Each data type has a set of built-in methods that only work on that data type. Check the Python data types docs to see which methods are available for a given data type.
    + Examples of string methods are:

    + + + + + + + + + + + +
    Function + Description +
    .upper() + Returns a copy of the string with all characters converted to uppercase +
    .lower() + Returns a copy of the string with all characters converted to lowercase +
    .title() + Returns a titlecased version of the string where words start with an uppercase character and the remaining characters are lowercase +
    .swapcase() + Returns a copy of the string with uppercase characters converted to lowercase and vice versa +
    .strip() + Returns a copy of the string with the leading and trailing whitespace characters removed +
    + +
    +
    +

    Syntax tips

    +
    +
    +

    String syntax

    + +

    Make sure you wrap strings in quotes. Otherwise Python will think it's the name + of a variable or function.

    + +

    Quotes can be single or double, just be consistent.

    + + + + + + + + +
    Uh-Oh + Correct +
    +
    
    +                                    song_title = No Matter What
    +                                    song_artist = Calum Scott
    +                                    
    +
    +
    
    +                                    song_title = 'No Matter What'
    +                                    song_artist = 'Calum Scott'
    +                                    
    +
    +
    
    +                                    play_song(Older, Ben Platt)
    +                                    
    +
    +
    
    +                                    play_song("Older", "Ben Platt")
    +                                    
    +
    +
    
    +                                    show_lyrics("True Colors', "Cyndi Lauper')
    +                                    
    +
    +
    
    +                                    play_song("True Colors", "Cyndi Lauper")
    +                                    
    +
    
    +                                    play_song('True Colors', 'Cyndi Lauper')
    +                                    
    +
    +
    +
    +

    Comment syntax

    + +

    A comment is human-readable text that's ignored by the Python interpreter.

    + +
    
    +                    # A single-line comment starts with a hash sign
    +                    x = 4 # A comment can also go at the end of the line
    +
    +                    """
    +                    Multi-line comments
    +                    start and end with three quotes.
    +                    """
    +                    
    + +
    + +
    +

    Commenting out

    + +

    A common programming practice is to "comment things out" + while debugging code. That allows you to see how your + program works without a line of code and see whether that + affects the execution or fixes a bug. +

    + +
    
    +                    x = 5
    +                    y = 10
    +                    #z = x ** y
    +                    z = pow(x, y)
    +                    
    +
    + +
    +

    Documenting with comments

    + +

    Programmers often use comments to explain + segments of code that aren't obvious. +

    + +
    
    +                    h = 50 # Hue from 0-360
    +                    s = 99 # Saturation from 0-100
    +                    v = 50 # Value from 0-100
    +                    
    +
    +
    +

    Functions intro

    +
    + +
    +

    What is a function?

    + +

    A function is a sequence of code that performs a particular task + and can be easily reused. ♻️ +

    + +

    We've already used functions!

    + +
    
    +                    add(18, 69)
    +                    mul(60, sub(5, 4))
    +                    
    + +
    +

    A function takes input(s) (the arguments) and returns an output (the return value).

    + +

    18, 69 β†’ add β†’ 87 +

    +
    +
    +
    +

    Why functions?

    + +

    Consider this function-less code:

    +
    
    +                    greeting1 = "Hello, Jackson, how are you?";
    +                    greeting2 = "Hello, Dr. Biden, how are you?";
    +                    greeting3 = "Hello, Stranger, how are you?";
    +                    
    + +

    Functions help when code has repetition.

    + +

    Function parameters help when that repetitive code has variation.

    +
    + +
    +

    Building a function

    + +

    First identify the repetitive parts:

    + +
    
    +                    def say_greeting():
    +                        return "Hello, how are you?"
    +                    
    + +

    Then use parameters for the parts that vary:

    +
    
    +                    def say_greeting(name):
    +                        return "Hello, " + name + ", how are you?"
    +                    
    + +

    Finally, test it with different arguments:

    +
    
    +                    greeting1 = say_greeting("Jackson");
    +                    greeting2 = say_greeting("Dr. Biden")
    +                    greeting3 = say_greeting("Stranger")
    +                    
    +
    +
    +

    Defining functions

    +
    + +
    +

    Defining functions

    + +

    The most common way to define functions is Python is the def statement.

    + +
    
    +                    def <name>(<parameters>):
    +                        return <return expression>
    +                    
    + +

    Example:

    +
    
    +                    def add(num1, num2):
    +                        return num1 + num2
    +                    
    + +

    Once defined, we can call it:

    +
    
    +                    add(2, 2)
    +                    add(18, 69)
    +                    
    +
    + +
    +

    Anatomy of a function definition

    + +

    The first line is called the function signature, + all lines after are considered the function body.

    + +
    
    +                    def <name>(<parameters>):        # ← Function signature
    +                        return <return expression>   # ← Function body
    +                    
    + + +
    
    +                    def add(num1, num2):             # ← Function signature
    +                        return num1 + num2           # ← Function body
    +                    
    + +
    +

    The function body can have multiple lines:

    + +
    
    +                    def add(num1, num2):             # ← Function signature
    +                        sum = num1 + num2            # ← Function body
    +                        return sum                   # ← Function body
    +                    
    +
    +
    + +
    +

    Function arguments

    + +

    We can pass in any expressions as arguments.

    + +
    
    +                    def add(num1, num2):
    +                        return num1 + num2
    +                    
    + +
    
    +                    x = 1
    +                    y = 2
    +                    add(x, y)
    +                    
    + +
    
    +                    x = 3
    +                    add(x * x, x + x)
    +                    
    +
    + +
    +

    Return values

    + +

    The return keyword returns a value to whoever calls the function (and exits the function).

    + +
    
    +                    def add(num1, num2):
    +                        return num1 + num2
    +
    +                    sum = add(2, 4)
    +                    
    + +

    Reminder: You can use function calls in expressions:

    +
    
    +                    big_sum = add(200, 412) + add(312, 256)
    +                    
    + +

    ...and nest function calls inside function calls:

    +
    
    +                    huge_sum = add(add(200, 412), add(312, 256))
    +                    
    +
    + +
    +

    Spot the bug #1

    + +

    What's wrong with this code?

    +
    
    +                    def add(num1, num2):
    +                        return sum
    +                        sum = num1 + num2
    +
    +                    sum = add(2, 4)
    +                    
    + +

    The code after the return statement will not be executed, + that line belongs before the return.

    +
    + +
    +

    Spot the bug #2

    +

    What's wrong with this code?

    +
    
    +                    def add():
    +                        return num1 + num2
    +
    +                    sum = add(2, 4)
    +                    
    +

    The function body is referring to variables + that don't seem to exist. Most likely, they should be parameters + in the function signature.

    +
    + +
    +

    Spot the bug #3

    + +

    What's wrong with this code?

    +
    
    +                    def add(num1, num2):
    +                        sum = num1 + num2
    +
    +                    sum = add(2, 4)
    +                    
    +

    The function body does not return any value. + However, the code that calls it tries to use the result of the expression. + It should have a return statement that returns the sum. +

    +
    +
    +

    Challenge question

    + +

    What will happen if we run the following code?

    +
    
    +                    from operator import add
    +
    +                    def add(num1, num2):
    +                        response = num1 * num2
    +                        return response
    +
    +                    sum = add(2, 4)
    +                    print(sum)
    +                    
    +

    Remember from class 1, names can be reassigned! This is true for both variables and functions. A name will always refer to its last assigned value. +

    +
    + +
    +

    Exercise

    +

    Let's work on this together!

    +

    Open the Class2Ex1DogAge repl and click Fork repl.

    +
    +
    +

    Forking Replit files

    +
      +
    1. Click the link to the Replit, ex https://replit.com/@lizkrznarich/Class2Ex1DogAge +
    2. Click Fork Replit
      + +
    3. Click Edit in workspace + +
    +
    + +
    +

    More on names

    +
    +
    +

    Namespaces

    + +

    Python uses the concept of namespaces to organize the symbolic names assigned to objects, like variables and functions. Namespaces help to avoid name conflicts.
    + Python has 4 levels of namespaces: + + + + + +
    Built-in + Contains the names of all of Python’s built-in objects (ex, functions like print() and pow()) +
    Global + Contains any names defined at the level of the main program (ie, variable & function names that are NOT indented) +
    Enclosing + When functions are nested, contains names defined inside a parent function (ie, variabl & function names that are indented) +
    Local + Contains names defined inside a function (ie, variable names that are indented) +
    +

    +
    +

    Example: Global vs Local names

    +

    In practice, we mostly care about whether a name is global or local.

    + + + +
    Global + screenshot showing global env +
    Local + screenshot showing +
    +
    +
    +

    Name look-up

    + +

    Multiple namespaces means that multiple variables, functions, etc can have the same name without conflicting, as long as they are in different namespaces.

    +

    But how does Python know which namespace to look in?

    +

    It follows the LEGB rule!

    + + +
    +
    +

    Name look-up

    + If your code has a variable named x, Python searches for where x is defined in this order: +
      +
    1. Local: If you refer to x inside a function, Python first searches within that function +
    2. Enclosing: If x isn’t in the local namespace but appears in a function that resides inside another function, Python searches in the enclosing function +
    3. Global: If neither of the above searches is fruitful, Python looks in the global namespace +
    4. Built-in: If it can’t find where x is defined anywhere else, Python tries the built-in namespace +
    +

    If a definition for x isn't found, a name error is thrown

    +
    + +
    +

    Why do we care about namespaces?

    +
      +
    • Avoid name errors +
    • Make sure we're using the function or variable that we intend to +
    • Make sure we can access the value of a variable/function where it's needed +
    +

    Example: Multiple functions with the same name

    +
    
    +                        # this calls pow() from the built-in namespace
    +                        print(pow(3,4))
    +                        # now we define pow() in the global namespace
    +                        def pow(x, y):
    +                            return("POW! " + str(x) + str(y))
    +                        # this calls pow() from the global namespace
    +                        print(pow(3,4))
    +                        
    +
    +
    +

    Why do we care about namespaces?

    +

    Example: Variable that we can't access

    +
    
    +                        def my_function(x, y):
    +                            # z is defined in the local namespace
    +                            z = x + y
    +                            return z**x
    +                        # what if we want to use z later in the program?
    +                        # z is not defined globally, so we can't access it here
    +                        print(z)
    +                    
    +
    + + +
    +

    Name lookup example #1

    + +
    
    +                    def exclamify(text):
    +                        start_exclaim = "Β‘"
    +                        end_exclaim = "!"
    +                        return start_exclaim + text + end_exclaim
    +
    +                    exclamify("the snails are eating my lupines")
    +                    
    + +
      +
    • On line 4, which namespace is start_exclaim found in?
      The local frame for exclamify +
    • On line 4, Which namespace is text found in?
      The local frame for exclamify +
    • On line 6, which namespace is exclamify found in?
      The global frame +
    +
    + +
    +

    Name lookup example #2

    + +
    
    +                    start_exclaim = "Β‘"
    +                    end_exclaim = "❣️"
    +
    +                    def exclamify(text):
    +                        return start_exclaim + text + end_exclaim
    +
    +                    exclamify("the voles are digging such holes")
    +                    
    + +
      +
    • On line 5, which namespace is start_exclaim found in?
      The global frame +
    • On line 5, Which namespace is text found in?
      The local frame for exclamify +
    • On line 6, which namespace is exclamify found in?
      The global frame +
    +
    + +
    +

    Name lookup example #3

    + +
    
    +                    def exclamify(text):
    +                        end_exclaim = "⁉️️️"
    +                        return start_exclaim + text + end_exclaim
    +
    +                    exclamify("the voles are digging such holes")
    +                    
    + +
      +
    • Which name will cause a NameError?
      + The start_exclaim name, since it was never assigned. +
    • When will that error happen?
      + It will happen when exclamify is called and Python tries to execute the return statement. +
    +
    +
    +

    More on functions

    +
    + + +
    +

    Side effects

    +
    + +
    +

    The None value

    + +

    The special value None represents nothingness in Python.

    + +

    Any function that doesn't explicitly return a value will return None:

    + +
    
    +                    def square_it(x):
    +                      x * x
    +                    
    + +
    +

    When a function returns None, the console shows no output at all:

    +
    
    +                    square_it(4)
    +                    
    +
    +
    +

    Attempting to treat the None like a number will result in an error:

    +
    
    +                    sixteen = square_it(4)
    +                    sum = sixteen + 4     # 🚫 TypeError!
    +                    
    +
    + +
    +
    +

    Side effects

    + +

    A side effect is when something happens as a result of calling a function + besides just returning a value.

    + +

    The most common side effect is logging to the console, via the built-in print() function.

    + +
    
    +                    print(-2)
    +                    
    + +

    A similar side effect is writing to a file:

    + +
    
    +                    f = open('songs.txt', 'w')
    +                    f.write("Dancing On My Own, Robyn")
    +                    f.close()
    +                    
    + +
    + +
    +

    Side effects vs. Return values

    + +
    
    +                    def square_num1(number):
    +                        return pow(number, 2)
    +                    
    + +
    
    +                    def square_num2(number):
    +                        print(number ** 2)
    +                    
    + +
      +
    • Which one has a side effect?
      + The second function has a side effect, + because it prints to the console. +

      +
    • What data type do they each return? +
      + The first function returns a number, + the second one returns None. +

      + +
    + +
    +

    Default arguments

    + +

    In the function signature, a parameter can specify a default value. + If that argument isn't passed in, the default value is used instead.

    + +
    
    +                    def calculate_dog_age(human_years, multiplier = 7):
    +                        return human_years * multiplier
    +                    
    + +

    These two lines of code have the same result:

    +
    
    +                    calculate_dog_age(3)
    +                    calculate_dog_age(3, 7)
    +                    
    + +

    Default arguments can be overriden:

    +
    
    +                    calculate_dog_age(3, 6)
    +                    
    +
    + +
    +

    Multiple return values

    + +

    A function can specify multiple return values, separated by commas.

    + +
    
    +                    def divide_exact(n, d):
    +                        quotient = n // d
    +                        remainder = n % d
    +                        return quotient, remainder
    +                    
    + +

    Any code that calls that function must also "unpack it" using commas:

    + +
    
    +                    q, r = divide_exact(618, 10)
    +                    
    +
    +
    +

    Practice exercises

    + +

    Work on these functions in this order. Don't worry if you don't get through all of them!

    + + +

    Note! If you press Run while viewing the solution.py file, nothing will happen. This is because Repl is configured to run only the main.py file. To run the solution, copy the content of the solution to your main.py file.

    +
    +
    +
    + + + + + + + + + diff --git a/deloitte-python-1-aug-2022/class3/class3.html b/deloitte-python-1-aug-2022/class3/class3.html new file mode 100644 index 0000000..7c72042 --- /dev/null +++ b/deloitte-python-1-aug-2022/class3/class3.html @@ -0,0 +1,938 @@ + + + + + + Conditionals + + + + + + + + +
    +
    + +
    +

    Conditionals & Loops

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + +
    +

    Class outline:

    + +
      +
    • Review +
    • Booleans +
    • Conditionals +
    • Loops intro +
    +
    + +
    +

    Review

    +
    + +
    +

    Defining functions

    + +

    We define functions in Python with a def statement.

    + +
    
    +                    def <name>(<parameters>):
    +                        return <return expression>
    +                    
    + +

    Example:

    +
    
    +                        def add(num1, num2):             # ← Function signature
    +                            sum = num1 + num2            # ← Function body
    +                            return sum                   # ← Function body
    +                        
    +

    Once defined, we can call it:

    +
    
    +                    add(2, 2)
    +                    add(18, 69)
    +                    
    +
    +
    +

    Function arguments

    + +

    We can pass in any expressions as arguments.

    + +
    
    +                    def add(num1, num2):
    +                        return num1 + num2
    +                    
    + +
    
    +                    x = 1
    +                    y = 2
    +                    add(x, y)
    +                    
    + +
    
    +                    x = 3
    +                    add(x * x, x + x)
    +                    
    +
    +
    +

    Return values

    + +

    The return keyword returns a value to whoever calls the function (and exits the function).

    + +
    
    +                    def add(num1, num2):
    +                        return num1 + num2
    +
    +                    sum = add(2, 4)
    +                    
    +
    +
    +

    Namespaces

    + +

    Python uses the concept of namespaces to organize the symbolic names assigned to objects, like variables and functions. Namespaces help to avoid name conflicts.
    + Python has 4 levels of namespaces: + + + + + +
    Built-in + Contains the names of all of Python’s built-in objects (ex, functions like print() and pow()) +
    Global + Contains any names defined at the level of the main program (ie, variable & function names that are NOT indented) +
    Enclosing + When functions are nested, contains names defined inside a parent function (ie, variabl & function names that are indented) +
    Local + Contains names defined inside a function (ie, variable names that are indented) +
    +

    +
    +

    Example: Global vs Local names

    +

    In practice, we mostly care about whether a name is global or local.

    + + + +
    Global + screenshot showing global env +
    Local + screenshot showing +
    +
    +
    +

    Side effects

    + +

    A side effect is when something happens as a result of calling a function + besides just returning a value.

    + +

    The most common side effect is logging to the console, via the built-in print() function.

    + +
    
    +                    print(-2)
    +                    
    + +

    A similar side effect is writing to a file:

    + +
    
    +                    f = open('songs.txt', 'w')
    +                    f.write("Dancing On My Own, Robyn")
    +                    f.close()
    +                    
    + +
    + +
    +

    Side effects vs. Return values

    + +
    
    +                    def square_num1(number):
    +                        return pow(number, 2)
    +                    
    + +
    
    +                    def square_num2(number):
    +                        print(number ** 2)
    +                    
    + +
    + +
    +

    Default arguments

    + +

    In the function signature, a parameter can specify a default value. + If that argument isn't passed in, the default value is used instead.

    + +
    
    +                    def calculate_dog_age(human_years, multiplier = 7):
    +                        return human_years * multiplier
    +                    
    + +

    These two lines of code have the same result:

    +
    
    +                    calculate_dog_age(3)
    +                    calculate_dog_age(3, 7)
    +                    
    + +

    Default arguments can be overriden:

    +
    
    +                    calculate_dog_age(3, 6)
    +                    
    +
    + +
    +

    Multiple return values

    + +

    A function can specify multiple return values, separated by commas.

    + +
    
    +                    def divide_exact(n, d):
    +                        quotient = n // d
    +                        remainder = n % d
    +                        return quotient, remainder
    +                    
    + +

    Any code that calls that function must also "unpack it" using commas:

    + +
    
    +                    q, r = divide_exact(618, 10)
    +                    
    +
    +
    +

    Practice exercise review

    + +

    Let's review the homework from last week together!

    + + +

    (Note: we did Class2Ex2TemperatureConverter together in class)

    +
    + +
    +

    Boolean expressions

    +
    + +
    +

    Booleans

    + +

    A Boolean value is either True or False + and is used frequently in computer programs.

    + +

    Google Maps uses a boolean to decide whether to avoid highways in driving directions:

    +
    
    +                    avoid_highways = True
    +                    
    + +

    Twitter uses a boolean to remember where the user allows personalized ads:

    +
    
    +                    personalized_ads = False
    +                    
    +
    + +
    +

    Boolean expressions

    + +

    An expression can evaluate to a Boolean. + Most Boolean expressions use either comparison or logical operators. +

    +
    +

    An expression with a comparison operator:

    +
    
    +                    passed_class = grade > 65
    +                    
    +
    +

    An expression with a logical operator:

    +
    
    +                    wear_jacket = is_raining or is_windy
    +                    
    +

    Let's try it in Replit . Create a new Python 3 Repl.

    +
    + +
    +

    Comparison operators

    + + + + + + + +
    Operator Meaning True expressions +
    == Equality 32 == 32, "foo" == "foo" +
    != Inequality 30 != 32, "foo" != "bar" +
    > Greater than 60 >= 32 +
    >=Greater than or equal 60 >= 32 , 32 >= 32 +
    < Less than 20 < 32 +
    <= Less than or equal 20 <= 32, 32 <= 32 +
    +
    +
    +
    +

    Comparison operators

    +

    ⚠️ Common mistake: Do not confuse = (the assignment operator) with == (the equality operator).

    +
    
    +                            x = y
    +                        
    +

    is very different from

    +
    
    +                            x == y
    +                        
    +
    + + + +
    +

    Logical operators

    + + + + + +
    OperatorTrue expressions Meaning +
    and 4 > 0 and -2 < 0 True if both conditions are true; otherwise evaluates to False. Same as && in other languages. +
    or 4 > 0 or -2 > 0 True if either condition is true; evaluates to False only if both are false. Same as || in other languages. +
    not not (5 == 0) True if condition is false; evaluates to False if condition is true. Same as ! in other languages. +
    +

    W3Schools has a handy Python operators reference

    +
    +
    +

    Logical operators

    + +

    You might recognize logical operators from Advanced Search tools, like in Google Advanced Search

    + Screenshot of Google advanced search +
    + + +
    +

    Compound booleans

    + +

    When combining multiple operators in a single expression, use parentheses to group:

    +
    
    +                    may_have_mobility_issues = (age >= 0 and age < 2)  or age > 90
    +                    
    +
    + +
    +

    Boolean expressions in functions

    + +

    A function can use a Boolean expression to return a result based on the + values of the parameters.

    + +
    
    +                    def passed_class(grade):
    +                        return grade > 65
    +                    
    + +
    
    +                    def should_wear_jacket(is_rainy, is_windy):
    +                        return is_rainy or is_windy
    +                    
    +
    + +
    +

    Exercise: Booleans

    +

    Open Class3Ex1Booleans in Replit and click "Fork Repl" to create your own copy

    +

    We'll do the first question together; the rest will be homework for the next class.

    +
    + +
    +

    Conditionals

    +
    + +
    +

    Conditional statements

    + +

    A conditional statement gives you a way to execute + a different set of code statements based on whether certain + conditions are true or false.

    + +
    
    +                    if <condition>:
    +                        <statement>
    +                        <statement>
    +                        ...
    +                    
    + +

    A simple conditional:

    + +
    
    +                    clothing = "shirt"
    +
    +                    if temperature < 32:
    +                        clothing = "jacket"
    +                    
    + +

    In what situations will clothing be assigned to "jacket"?

    +
    +
    +

    The else statement

    + +

    A conditional can include an else statement + to specify code to execute when the if condition is False

    + +
    
    +                    if <condition>:
    +                        <statement>
    +                    else <condition>:
    +                        <statement>
    +                    
    + +
    
    +                    if temperature < 0:
    +                        clothing = "snowsuit"
    +                    else:
    +                        clothing = "jacket"
    +                    
    +
    + +
    +

    The elif statement

    + +

    When you have more than 1 condition you want to check, you can use elif + statements to check other conditions. Works kind of like a "choose your own adventure" book!

    + +
    
    +                    if <condition>:
    +                        <statement>
    +                        ...
    +                    elif <condition>:
    +                        <statement>
    +                        ...
    +                    elif <condition>:
    +                        <statement>
    +                        ...
    +                    
    + +
    
    +                    clothing = "shirt"
    +
    +                    if temperature < 0:
    +                        clothing = "snowsuit"
    +                    elif temperature < 32:
    +                        clothing = "jacket"
    +                    
    + +
    +
    +

    elif + else

    + +

    else can be used along with 1 or more elif statements + to specify code to execute as a last resort, if no previous conditions are true.

    + +
    
    +                    if <condition>:
    +                        <statement>
    +                        ...
    +                    elif <condition>:
    +                        <statement>
    +                        ...
    +                    else <condition>:
    +                        <statement>
    +                        ...
    +                    
    + +
    
    +                    if temperature < 0:
    +                        clothing = "snowsuit"
    +                    elif temperature < 32:
    +                        clothing = "jacket"
    +                    else:
    +                        clothing = "shirt"
    +                    
    + +
    + + +
    +

    Understanding conditionals

    + +
    
    +                    clothing = "shirt"
    +                    if temperature < 0:
    +                        clothing = "snowsuit"
    +                    elif temperature < 32:
    +                        clothing = "jacket"
    +                    else:
    +                        clothing = "shirt"
    +                    
    + + + + + + + + + + + + + + + + + + +
    temperatureclothing +
    -50snowsuit
    -1snowsuit
    0jacket
    1jacket
    31jacket
    32shirt
    50shirt
    +
    + + + +
    +

    Conditional statements summary

    + +
    
    +                    if num < 0:
    +                        sign = "negative"
    +                    elif num > 0:
    +                        sign = "positive"
    +                    else:
    +                        sign = "neutral"
    +                    
    + +

    Syntax tips:

    +
      +
    • Always start with if clause. +
    • Zero or more elif clauses. +
    • Zero or one else clause, always at the end. +
    +
    + +
    +

    Conditional evaluation order

    + +

    How Python interprets a conditional:

    +
      +
    • Evaluate the condition in the first clause. +
    • If it's true, execute the suite of statements underneath + and skip the remaining caluses. +
    • Otherwise, continue to the next clause and repeat. +
    + Screenshot of a conditional statement + Screenshot of a conditional statement +
    + +
    +

    Conditionals in functions

    + +

    It's common for a conditional to be based on the value of + the parameters to a function.

    + +
    
    +                    def get_number_sign(num):
    +                        if num < 0:
    +                            sign = "negative"
    +                        elif num > 0:
    +                            sign = "positive"
    +                        else:
    +                            sign = "neutral"
    +                        return sign
    +                    
    + +
    
    +                    get_number_sign(50)  # "positive"
    +                    get_number_sign(-1)  # "negative"
    +                    get_number_sign(0)   # "neutral"
    +                    
    +
    + +
    +

    Returns inside conditionals

    + +

    A branch of a conditional can end in a return, + which exits the function entirely. +

    + +
    
    +                    def get_number_sign(num):
    +                        if num < 0:
    +                            return "negative"
    +                        elif num > 0:
    +                            return "positive"
    +                        else:
    +                            return "neutral"
    +                    
    + +
    
    +                    get_number_sign(50)  # "positive"
    +                    get_number_sign(-1)  # "negative"
    +                    get_number_sign(0)   # "neutral"
    +                    
    +
    +
    +

    Exercise: Conditionals

    +

    Class3Ex2Conditionals

    +

    We'll do the first question together; the rest will be homework for the next class

    +
    + +
    +

    Loops

    +
    +
    +

    Why loops?

    +

    Sometimes we need to do the same thing over and over, with different data.

    +

    Consider the following code...

    +
    
    +                    print(9 * 1)
    +                    print(9 * 2)
    +                    print(9 * 3)
    +                    print(9 * 4)
    +                    print(9 * 5)
    +                    
    + +

    This code is repetitive and variable, but the variability + is sequential - it just adds one to the right-hand side number each time. + In English, we could describe this as "print out the first 5 multiples of 9".

    + +

    We can simplify this code with a loop!

    +
    +
    +

    Types of loops

    +

    Python has 2 types of loops:

    +
      +
    • While: Runs code as long as a specified condition is True (unknown number of times)
    • +
    • For: Runs code for a specified set of values (known number of times)
    • +
    +
    +
    +

    While loops

    +
    +
    +

    While loops

    + +

    The while loop syntax:

    + +
    
    +                    while <condition>:
    +                        <statement>
    +                        <statement>
    +                    
    + +

    As long as the condition is true, the statements below it are executed.

    + +
    
    +                    multiplier = 1
    +                    while multiplier <= 5:
    +                        print(9 * multiplier)
    +                        multiplier += 1
    +                    
    + +

    The code is significantly shorter, and it can easily be extended + to loop for more or less iterations.

    + +
    +
    +

    Using a counter variable

    + +

    We need to tell a While loop when to stop, otherwise it might keep running forever!

    +

    It's common to use a counter variable + whose job is keeping track of the number of times the loop has run.

    + +
    
    +                    total = 0
    +                    counter = 0
    +                    while counter < 5:
    +                      total += pow(2, 1)
    +                      counter += 1
    +                    
    +
    +
    +

    Special assignment operators

    + +

    What's this += thing?

    +
      +
    • One of several "special" assignment operators
    • +
    • Does math on an existing variable value and assigns the result to that variable at the same time
    • +
    • A handy shortcut counter += 1 does the same thing as counter = counter + 1
    • +
    +

    Can also subtract -=, multiply *=, divide /= and assign the result

    +

    See the full list of special assignment operators on W3Schools

    +
    +
    +

    Using a counter variable

    + +

    How many times will this loop run?

    + +
    
    +                    total = 0
    +                    counter = 0
    +                    while counter < 5:
    +                      total += pow(2, 1)
    +                      counter += 1
    +                    
    + +

    The loop runs while counter is 0, 1, 2, 3 and 4, so 5 times

    +
    +
    +

    Changing a while loop #1

    + +

    You can change the initial values of the variables used in the condition:

    + +
    
    +                    multiplier = 3
    +                    while multiplier <= 5:
    +                        print(9 * multiplier)
    +                        multiplier += 1
    +                    
    + +
      +
    • What will be the first thing displayed? 27 +
    • What will be the last thing displayed? 45 +
    • How many iterations? 3 (for values of 3, 4, 5) +
    +
    + +
    +

    Changing a while loop #2

    + +

    You can change the condition:

    +
    
    +                    multiplier = 3
    +                    while multiplier <= 10:
    +                        print(9 * multiplier)
    +                        multiplier += 1
    +                    
    + +
      +
    • What will be the first thing displayed? 27 +
    • What will be the last thing displayed? 90 +
    • How many iterations? 8 (for values of 3, 4, 5, 6, 7, 8, 9, 10) +
    +
    + +
    +

    Changing a while loop #3

    + +

    You can change how much the values change between iterations:

    +
    
    +                    multiplier = 3
    +                    while multiplier <= 10:
    +                        print(9 * multiplier)
    +                        multiplier += 2
    +                    
    + +
      +
    • What will be the first thing displayed? 27 +
    • What will be the last thing displayed? 81 +
    • How many iterations? 4 (for values of 3, 5, 7, 9) +
    +
    + +
    +

    Beware infinite loops

    + +

    Uh oh..

    +
    
    +                    counter = 1
    +                    while counter < 5:
    +                        total += pow(2, counter)
    +                    
    + +

    What one line of code would fix this? +
    counter += 1 +

    + +
    +
    
    +                    counter = 6
    +                    while counter > 5:
    +                      total += pow(2, counter)
    +                      counter += 1
    +                    
    + +

    How do we save this code? +
    Intentions are unclear! Change the initial value and condition? +

    +
    +
    +
    +

    The break statement

    + +

    To prematurely exit a loop, use the break statement:

    + +
    
    +                    counter = 100
    +                    while counter < 200:
    +                        if counter % 7 == 0:
    +                            first_multiple = counter
    +                            break
    +                        counter += 1
    +                    
    +
    +
    +

    Loops in functions

    + +

    A loop in a function will commonly use a parameter to determine some aspect of its repetition.

    + +
    
    +                    def sum_up_squares(start, end):
    +                        counter = start
    +                        total = 0
    +                        while counter <= end:
    +                          total += pow(counter, 2)
    +                          counter += 1
    +                        return total
    +
    +                    sum_up_squares(1, 5)
    +                    
    +
    +
    +

    Exercise: While loops

    +

    Class3Ex3WhileLoops

    +

    We'll do the first question together; the rest will be homework for the next class

    +
    +
    +

    Homework!

    +

    Finish the rest of the questions in each exercise - we'll review in the next class

    + + +
    +
    +

    How is it going?

    +

    Please fill out the feedback form to let me know how I can improve the class!

    +

    https://forms.gle/iENMqYvdahR9AP5UA

    +
    + + + + +
    +
    + + + + + + + + + diff --git a/deloitte-python-1-aug-2022/class4/class4.html b/deloitte-python-1-aug-2022/class4/class4.html new file mode 100644 index 0000000..d8ca8e0 --- /dev/null +++ b/deloitte-python-1-aug-2022/class4/class4.html @@ -0,0 +1,717 @@ + + + + + + Lists + + + + + + + + +
    +
    + +
    +

    Lists & Loops

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + +
    +

    Class outline:

    + +
      +
    • Review +
    • Data structures +
    • Lists +
    • For loops +
    • Nested lists +
    +
    +
    +

    Review

    +
    +
    +

    Booleans

    + +

    A Boolean value is either True or False + and is used frequently in computer programs.

    + +

    Google Maps uses a boolean to decide whether to avoid highways in driving directions:

    +
    
    +                    avoid_highways = True
    +                    
    + +

    Twitter uses a boolean to remember where the user allows personalized ads:

    +
    
    +                    personalized_ads = False
    +                    
    +
    + +
    +

    Boolean expressions

    + +

    An expression can evaluate to a Boolean. + Most Boolean expressions use either comparison or logical operators. +

    +
    +

    An expression with a comparison operator:

    +
    
    +                    passed_class = grade > 65
    +                    
    +
    +

    An expression with a logical operator:

    +
    
    +                    wear_jacket = is_raining or is_windy
    +                    
    +
    + +
    +

    Comparison operators

    + + + + + + + +
    Operator Meaning True expressions +
    == Equality 32 == 32 +
    != Inequality 30 != 32 +
    > Greater than 60 >= 32 +
    >=Greater than or equal 60 >= 32 , 32 >= 32 +
    < Less than 20 < 32 +
    <= Less than or equal 20 < 32, 32 <= 32 +
    +
    +

    ⚠️ Common mistake: Do not confuse = (the assignment operator) with == (the equality operator).

    +
    +
    +

    Comparison operators

    +

    ⚠️ Common mistake: Do not confuse = (the assignment operator) with == (the equality operator).

    +
    
    +                            x = y
    +                        
    +

    is very different from

    +
    
    +                            x == y
    +                        
    +
    +
    +

    Logical operators

    + + + + + +
    OperatorTrue expressions Meaning +
    and 4 > 0 and -2 < 0 Evaluates to True if both cconditions are true; otherwise evaluates to False. +
    or 4 > 0 or -2 > 0 Evaluates to True if either condition is true; evaluates to False only if both are false. +
    not not (5 == 0) Evaluates to True if condition is false; evaluates to False if condition is true. +
    +

    W3Schools has a handy Python operators reference

    +
    +
    +

    Conditional statements

    + +

    A conditional statement gives you a way to execute + a different set of code statements based on whether certain + conditions are true or false.

    + +
    
    +                    if <condition>:
    +                        <statement>
    +                        <statement>
    +                        ...
    +                    
    + +

    A simple conditional:

    + +
    
    +                    clothing = "shirt"
    +
    +                    if temperature < 32:
    +                        clothing = "jacket"
    +                    
    +
    +
    +

    if/elif/else statements summary

    + +
    
    +                        def get_number_sign(num):
    +                            if num < 0:
    +                                sign = "negative"
    +                            elif num > 0:
    +                                sign = "positive"
    +                            else:
    +                                sign = "neutral"
    +                            return sign
    +                    
    + +

    Syntax tips:

    +
      +
    • Always start with if clause. +
    • Zero or more elif clauses. +
    • Zero or one else clause, always at the end. +
    +
    +
    +

    While loops

    + +

    The while loop syntax:

    + +
    
    +                    while <condition>:
    +                        <statement>
    +                        <statement>
    +                    
    + +

    As long as the condition is true, the statements below it are executed.

    + +
    
    +                    multiplier = 1
    +                    while multiplier <= 5:
    +                        print(9 * multiplier)
    +                        multiplier += 1
    +                    
    + +
    +
    +

    Using a counter variable

    + +

    We need to tell a While loop when to stop, otherwise it might keep running forever!

    +

    It's common to use a counter variable + whose job is keeping track of the number of times the loop has run.

    + +
    
    +                    total = 0
    +                    counter = 0
    +                    while counter < 5:
    +                      total += pow(2, 1)
    +                      counter += 1
    +                    
    +
    +
    +

    Special assignment operators

    + +

    What's this += thing?

    +
      +
    • One of several "special" assignment operators
    • +
    • Does math on an existing variable value and assigns the result to that variable at the same time
    • +
    • A handy shortcut counter += 1 does the same thing as counter = counter + 1
    • +
    +

    Can also subtract -=, multiply *=, divide /= and assign the result

    +

    See the full list of special assignment operators on W3Schools

    +
    +
    +

    Loops in functions

    + +

    A loop in a function will commonly use a parameter to determine some aspect of its repetition.

    + +
    
    +                    def sum_up_squares(start, end):
    +                        counter = start
    +                        total = 0
    +                        while counter <= end:
    +                          total += pow(counter, 2)
    +                          counter += 1
    +                        return total
    +
    +                    sum_up_squares(1, 5)
    +                    
    +
    +
    +

    Practice exercise review

    + +

    Let's review the homework from last week together!

    + + +

    Note: We did the first problem from each exercise together in class

    +
    +
    +

    Data structures

    +
    +
    +

    Data structures

    + +

    A data structure is a particular way of organizing data in a computer so that it can be used effectively.

    +
    +

    Data structures in programming are a bit like lists and tables in text docs/presentations - we use them to organize information and make it more meaningful/useful.

    + + +
    + +
    +

    Lists

    +
    + +
    +

    Lists

    +

    A list is a container that holds a sequence of related pieces of information.

    +

    The shortest list is an empty list, just 2 square brackets:

    +
    
    +                    members = []
    +                    
    +

    Lists can hold any Python values, separated by commas:

    +
    
    +                    # all strings
    +                    members = ["Liz", "Tinu", "Brenda", "Kaya"]
    +                    # all integers
    +                    ages_of_kids = [1, 2, 7]
    +                    # all floats
    +                    prices = [79.99, 49.99, 89.99]
    +                    # mixed types
    +                    mixed_types = ["Liz", 7, 79.99]
    +                    
    +
    +
    +

    Accessing items (Bracket notation)

    + +

    Lists are ordered. Each list item has an index, starting from 0.

    + +
    
    +                    temps = [48.0, 30.5, 20.2, 99.0, 52.0]
    +                    # Index:   0     1     2     3     4
    +                    
    + +

    Access each item by putting the index in brackets:

    +
    
    +                    temps[0]  # 48.0
    +                    temps[1]  # 30.5
    +                    temps[2]  # 20.2
    +                    temps[3]  # 99.0
    +                    temps[4]  # 52.0
    +                    temps[5]  # 🚫 Error!
    +                    
    +
    + +
    +

    List length

    + +

    Use the global len() function + to find the length of a list.

    + +
    
    +                    attendees = ["Tammy", "Shonda", "Tina"]
    +
    +                    print(len(attendees))   #  3
    +
    +                    num_of_attendees = len(attendees)
    +                    print(num_of_attendees)
    +                    
    + +

    πŸ€” What could go wrong with storing the length?

    + +
    + +
    +

    Exercises: Making lists

    + +
    + +
    +

    Modifying list items

    + +

    Python lists are mutable, which means + you can change the values stored in them.

    +
    +

    Use bracket notation to modify single items in the list:

    +
    
    +                    temps = [48.0, 30.5, 20.2, 99.0, 52.0]
    +                    temps[2] = 22.22
    +                    temps[-1] = 55.55
    +                    
    +
    +
    +

    What if we change the value of an item beyond the list length?

    +
    
    +                    temps[5] = 111.11 # 🚫 Error!
    +                    
    +
    +
    + +
    +

    Modifying lists with methods

    + + + + + + + + + + +
    Method + Description +
    append(item) + Adds item to the end of the list. This increases list length by one. +
    insert(index, item) + Inserts item at the specified index. This increases the list length by one and + shifts all items after the specified index forward by one index.

    +
    remove(item) + Remove the first item from the list whose value is equal to item. + It raises a ValueError if there is no such item. +
    index(item) + Returns the index of the first occurrence of an item whose value is equal to item. + It raises a ValueError if there is no such item. +
    pop([index]) + If no index is specified, it removes the last item from the list and returns it. + Otherwise, it removes the item at the specified index and returns it. +
    + +

    See more in Python.org documentation

    + +
    + +
    +

    Examples of list modifying methods

    + +
    
    +                    groceries = ["apples", "bananas"]
    +
    +                    groceries.append("peanut butter")
    +                    groceries.insert(0, "applesauce")
    +                    groceries.insert(3, "cheerios")
    +                    groceries.remove("bananas")
    +
    +                    bought_food = groceries.pop()
    +                    bought_food2 = groceries.pop(1)
    +                    i = groceries.index("cheerios")
    +                    bought_food3 = groceries.pop(i)
    +                    
    +
    + +
    +

    Exercise: Mutating lists

    + +

    We'll work on the first question together, and then you'll work on the rest individually.

    + +

    Repl: Class4Ex3ListMutator

    +
    +
    +

    For loops

    +
    +
    +

    For loop

    +

    The other type of loop supported in Python is a for loop

    +

    The for loop syntax:

    + +
    
    +                    for <value> in <sequence>:
    +                        <statement>
    +                        <statement>
    +                    
    + +

    For loops provide a clean way of repeating code for each item in a data structure (like a list).

    +
    +
    +

    For loops vs While lopps

    +

    for loops are for cases where the loop will run for a known number of times, ex for each item in a list

    +

    while loops are for cases where the loop may run for an unknown number of times, ex until a condition is no longer true

    +
    + +
    +

    Looping through a list

    + +

    😍 For loops love lists!

    +
    
    +                    scores = [80, 95, 78, 92]
    +                    total = 0
    +                    for score in scores:
    +                        total += score
    +                    
    +
    +

    This does the same thing as a while loop with a counter, but with less code.

    +
    
    +                    scores = [80, 95, 78, 92]
    +                    total = 0
    +                    i = 0
    +                    while i < len(scores):
    +                        score = scores[i]
    +                        total += score
    +                        i += 1
    +                    
    +
    +
    + +
    +

    Exercise: For loops

    +

    We'll work on the first question together, and then you'll work on the rest individually.

    +

    Repl: Class4Ex4ForInListLoops

    +
    + +
    +

    Nested Lists

    +
    + +
    +

    Nested Lists

    + +

    Since Python lists can contain any values, an item can itself be a list.

    + +
    +                    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2], # gymnasts[0]
    +                                    ["Lea", 9, 8.8, 9.1, 9.5], # gymnasts[1]
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8] # gymnasts[2]
    +                               ]
    +                    
    +

    You can think of nested lists like rows in a table:

    + +
    +
    +

    Nested Lists

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2], # gymnasts[0]
    +                                    ["Lea", 9, 8.8, 9.1, 9.5], # gymnasts[1]
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8] # gymnasts[2]
    +                               ]
    +                            
    +
      +
    • What's the length of gymnasts? 3 +
    • What's the length of gymnasts[0]? 5 +
    +
    +
    +

    Accessing nested list items

    + +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    + +

    Access using bracket notation, with more brackets as needed:

    +
    
    +                    gymnasts[0]    # ["Brittany", 9.15, 9.4, 9.3, 9.2]
    +                    gymnasts[0][0] # "Brittany"
    +                    gymnasts[1][0] # "Lea"
    +                    gymnasts[1][4] # 9.5
    +                    gymnasts[1][5] # 🚫 IndexError!
    +                    gymnasts[3][0] # 🚫 IndexError!
    +                    
    +
    +
    +

    Modifying nested lists: Bracket notation

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    +

    Modify using bracket notation as well, just like before:

    +
    
    +                    gymnasts[0] = ["Olivia", 8.75, 9.1, 9.6, 9.8]
    +                    gymnasts[1][0] = "Leah"
    +                    gymnasts[2][4] = 9.8
    +                    
    +
    +
    +

    Modifying nested lists: List methods

    +

    If we start with...

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5]
    +                               ]
    +                    
    +

    We can append another list a few ways:

    +
    
    +                    gymnasts.append(["Maya", 9.2, 8.7, 9.2, 8.8])
    +                    
    +
    
    +                    gymnasts += ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                    
    +
    
    +                    gymnast = []
    +                    gymnast.append("Maya")
    +                    gymnast.append(9.2)
    +                    gymnast.append(8.7)
    +                    gymnast.append(9.2)
    +                    gymnast.append(8.8)
    +                    gymnasts.append(gymnast)
    +                    
    +
    + +
    +

    Looping through nested lists

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    +

    Use a nested for-in loop:

    +
    
    +                    for gymnast in gymnasts:
    +                        for data in gymnast:
    +                            print(data, end="|")
    +                    
    +

    Remember what type of data is being stored in the loop variable!

    +
    +
    +

    Exercise: Nested for loops

    +

    Repl: Class4Ex5NestedForLoops

    +
    +
    +

    Homework!

    +

    Finish the rest of the questions in each exercise - we'll review in the next class

    + +
    +
    +

    How is it going?

    +

    Please fill out the feedback form to let me know how I can improve the class!

    +

    https://forms.gle/iENMqYvdahR9AP5UA

    +
    +
    +
    + + + + + + + + + diff --git a/deloitte-python-1-aug-2022/class5/class5.html b/deloitte-python-1-aug-2022/class5/class5.html new file mode 100644 index 0000000..0be7037 --- /dev/null +++ b/deloitte-python-1-aug-2022/class5/class5.html @@ -0,0 +1,637 @@ + + + + + + More with lists + + + + + + + + +
    +
    + +
    +

    More with lists!

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + +
    +

    Class outline:

    + +
      +
    • Review +
    • More list functionality +
    • Nested lists +
    • Getting data from CSV files +
    +
    +
    +

    Review

    +
    +
    +

    Data structures

    + +

    A data structure is a particular way of organizing data in a computer so that it can be used effectively.

    +
    +

    Data structures in programming are a bit like lists and tables in text docs/presentations - we use them to organize information and make it more meaningful/useful.

    + + +
    +
    +

    Lists

    +

    A list is a container that holds a sequence of related pieces of information.

    +

    The shortest list is an empty list, just 2 square brackets:

    +
    
    +                    members = []
    +                    
    +

    Lists can hold any Python values, separated by commas:

    +
    
    +                    # all strings
    +                    members = ["Liz", "Tinu", "Brenda", "Kaya"]
    +                    # all integers
    +                    ages_of_kids = [1, 2, 7]
    +                    # all floats
    +                    prices = [79.99, 49.99, 89.99]
    +                    # mixed types
    +                    mixed_types = ["Liz", 7, 79.99]
    +                    
    +
    +
    +

    Accessing items (Bracket notation)

    + +

    Lists are ordered. Each list item has an index, starting from 0.

    + +
    
    +                    temps = [48.0, 30.5, 20.2, 99.0, 52.0]
    +                    # Index:   0     1     2     3     4
    +                    
    + +

    Access each item by putting the index in brackets:

    +
    
    +                    temps[0]  # 48.0
    +                    temps[1]  # 30.5
    +                    temps[2]  # 20.2
    +                    temps[3]  # 99.0
    +                    temps[4]  # 52.0
    +                    temps[5]  # 🚫 Error!
    +                    
    +
    +
    +

    List length

    + +

    Use the global len() function + to find the length of a list.

    + +
    
    +                    attendees = ["Tammy", "Shonda", "Tina"]
    +
    +                    print(len(attendees))   #  3
    +
    +                    num_of_attendees = len(attendees)
    +                    print(num_of_attendees)
    +                    
    +
    +
    +

    Modifying list items

    + +

    Python lists are mutable, which means + you can change the values stored in them.

    +
    +

    Use bracket notation to modify single items in the list:

    +
    
    +                    temps = [48.0, 30.5, 20.2, 99.0, 52.0]
    +                    temps[2] = 22.22
    +                    temps[-1] = 55.55
    +                    
    +
    +
    +
    +

    Modifying lists with methods

    + + + + + + + + + + +
    Method + Description +
    append(item) + Adds item to the end of the list. This increases list length by one. +
    insert(index, item) + Inserts item at the specified index. This increases the list length by one and + shifts all items after the specified index forward by one index.

    +
    remove(item) + Remove the first item from the list whose value is equal to item. + It raises a ValueError if there is no such item. +
    index(item) + Returns the index of the first occurrence of an item whose value is equal to item. + It raises a ValueError if there is no such item. +
    pop([index]) + If no index is specified, it removes the last item from the list and returns it. + Otherwise, it removes the item at the specified index and returns it. +
    + +

    See more in Python.org documentation

    + +
    +
    +

    List method return values

    + +

    Most of the list mutation methods perform an action and don't return a value.

    +

    An exception is .pop(), which removes a list item and returns its value, so you can assign it to a variable.

    +
    
    +                    groceries = ["apples", "bananas"]
    +
    +                    bought_food = groceries.pop()
    +                    
    +
    +
    +

    For loop

    +

    The other type of loop supported in Python is a for loop

    +

    The for loop syntax:

    + +
    
    +                    for <value> in <sequence>:
    +                        <statement>
    +                        <statement>
    +                    
    + +

    For loops provide a clean way of repeating code for each item in a data structure (like a list).

    +
    +
    +

    Looping through a list

    +

    😍 For loops love lists!

    +
    
    +                    scores = [80, 95, 78, 92]
    +                    total = 0
    +                    for score in scores:
    +                        total += score
    +                    
    +
    +

    This does the same thing as a while loop with a counter, but with less code.

    +
    
    +                    scores = [80, 95, 78, 92]
    +                    total = 0
    +                    i = 0
    +                    while i < len(scores):
    +                        score = scores[i]
    +                        total += score
    +                        i += 1
    +                    
    +
    +
    +
    +

    Homework review!

    + +
    +
    +

    More list functionality

    +
    + +
    +

    Checking if value is in a list

    + +

    The in keyword checks if + a value is in a list (or any sequence).

    + +
    
    +                    if "bananas" in groceries:
    +                        print("Watch your step!")
    +
    +                    if "bleach" in groceries:
    +                        print("Watch what you eat!")
    +                    
    + +

    When used inside if conditions, in expressions return a Boolean (True/False).

    +
    +
    +

    Helpful list methods

    + + + + + + + + +
    Method + Description +
    count(item) + Returns the number of occurrences of item in the list. If item is not found, returns 0. +
    reverse() + Reverses the elements of the list in place. +
    sort([key=function]) + Sorts the items of the list in place. The optional key argument specifies + a function to compute a comparison key for each item in the list. Otherwise, items are compared based on their values. +
    + +

    See more in Python.org documentation

    +
    + +
    +

    Examples with reverse

    + +

    If we start with...

    +
    
    +                    nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    +                    spelling = ["B", "U", "M", "B", "L", "E"]
    +                    
    + +

    Then call the reverse method...

    +
    
    +                    nums.reverse()     # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
    +                    spelling.reverse() # ["E", "L", "B", "M", "U", "B"]
    +                    
    + +
    +

    What do you think of this?

    + +
    
    +                    nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    +                    reversed_nums = nums.reverse()
    +                    
    + +

    It's a bit strange, since reverse() + does an in-place reversal, so now the program has the same list in two variables!

    +
    +
    + + +
    +

    Examples with sort

    + +
    
    +                    foods = ["orange", "apple", "Pear", "banana"]
    +                    
    + +

    The simplest sort:

    +
    
    +                    foods.sort()
    +                    # ["Pear", "apple", "banana", "orange"]
    +                    
    + +

    Specifying a key argument of an existing function:

    +
    
    +                    foods.sort(key=str.lower)
    +                    # ["apple", "banana", "orange", "Pear"]
    +                    
    + +

    .sort() modifies a list in place. To sort a list into a new list, use the global sorted() function.

    +
    + +
    +

    Useful functions for lists

    + +

    These are functions, not methods.

    + + + + + + + + +
    Module + Function + Description +
    Global + min(list, [key=function]) + Returns the minimum value in list. The optional key argument specifies a custom comparator function. +
    Global + max(list, [key=function]) + Returns the maximum value in list. he optional key argument specifies a custom comparator function. +
    random + choice(list) + Returns a randomly selected item from list. +
    random + shuffle(list) + Shuffles the elements of the list in place. +
    +
    +
    +

    Nested Lists

    +
    +
    +

    Nested Lists

    + +

    Since Python lists can contain any values, an item can itself be a list.

    + +
    +                    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2], # gymnasts[0]
    +                                    ["Lea", 9, 8.8, 9.1, 9.5], # gymnasts[1]
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8] # gymnasts[2]
    +                               ]
    +                    
    +

    You can think of nested lists like rows in a table:

    + +
    +
    +

    Nested Lists

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2], # gymnasts[0]
    +                                    ["Lea", 9, 8.8, 9.1, 9.5], # gymnasts[1]
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8] # gymnasts[2]
    +                               ]
    +                            
    +
      +
    • What's the length of gymnasts? 3 +
    • What's the length of gymnasts[0]? 5 +
    +
    +
    +

    Accessing nested list items

    + +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    + +

    Access using bracket notation, with more brackets as needed:

    +
    
    +                    gymnasts[0]    # ["Brittany", 9.15, 9.4, 9.3, 9.2]
    +                    gymnasts[0][0] # "Brittany"
    +                    gymnasts[1][0] # "Lea"
    +                    gymnasts[1][4] # 9.5
    +                    gymnasts[1][5] # 🚫 IndexError!
    +                    gymnasts[3][0] # 🚫 IndexError!
    +                    
    +
    +
    +

    Modifying nested lists: Bracket notation

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    +

    Modify using bracket notation as well, just like before:

    +
    
    +                    gymnasts[0] = ["Olivia", 8.75, 9.1, 9.6, 9.8]
    +                    gymnasts[1][0] = "Leah"
    +                    gymnasts[2][4] = 9.8
    +                    
    +
    +
    +

    Modifying nested lists: List methods

    +

    If we start with...

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5]
    +                               ]
    +                    
    +

    We can append another list a few ways:

    +
    
    +                    gymnasts.append(["Maya", 9.2, 8.7, 9.2, 8.8])
    +                    
    +
    
    +                    gymnasts += ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                    
    +
    
    +                    gymnast = []
    +                    gymnast.append("Maya")
    +                    gymnast.append(9.2)
    +                    gymnast.append(8.7)
    +                    gymnast.append(9.2)
    +                    gymnast.append(8.8)
    +                    gymnasts.append(gymnast)
    +                    
    +
    + +
    +

    Looping through nested lists

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    +

    Use a nested for-in loop:

    +
    
    +                    for gymnast in gymnasts:
    +                        print(gymnast)
    +                        for data in gymnast:
    +                            print(data)
    +                    
    +

    Remember what type of data is being stored in the loop variable!

    +
    +
    +

    Exercise: Nested for loops

    +

    Repl: Class4Ex5NestedForLoops

    +
    +
    +

    Reading data from CSV files

    +
    +
    +

    CSV files

    +

    Comma Separated Value (CSV) is a plain text format used to store "tabular" data (aka rows and columns), like from a spreadsheet or database table.

    +

    Because CSV is simple and non-proprietary, it's commonly used to exchange data between different applications.

    +
    
    +                        Brittany, 9.15, 9.4, 9.3, 9.2
    +                        Lea, 9, 8.8, 9.1, 9.5
    +                        Maya, 9.2, 8.7, 9.2, 8.8
    +                    
    + +
    +
    +

    Opening files

    +

    We use the Python built in open() method to open files for reading or writing.

    +

    The keyword with tells Python to automatically close the file when we're finished.

    +
    
    +                        with open('filename') as my_file:
    +                            # do something
    +                    
    +
    +
    +

    Reading files with CSV module

    +

    Python has a built-in CSV module that includes many features used for reading/writing CSV files.

    + Open a CSV and read its contents +
    
    +                        # import the csv module
    +                        import csv
    +                        # open the file
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            # load the contents of the CSV file into a variable
    +                            csv_reader = csv.reader(my_file, delimiter=',')
    +                            # CSV is a nested list!
    +                            # now we can loop through the rows in the file
    +                            for row in csv_reader:
    +                                print(row)
    +                    
    +
    +
    +

    Reading files with CSV module

    +

    A CSV is a list of rows, which are lists of values.

    +

    We can use nested for loops to get values from rows and cells.

    +
    
    +                        import csv
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            csv_reader = csv.reader(my_file, delimiter=',')
    +                            for row in csv_reader:
    +                                print(row)
    +                                for cell in row:
    +                                    print(cell)
    +                    
    +
    +
    +

    Exercise: Getting data from CSV

    +

    Repl: Class5Ex2CsvData

    +
    +
    +

    Homework!

    + +
    +
    +
    + + + + + + + + + diff --git a/deloitte-python-1-aug-2022/class6/class6.html b/deloitte-python-1-aug-2022/class6/class6.html new file mode 100644 index 0000000..dd14d7b --- /dev/null +++ b/deloitte-python-1-aug-2022/class6/class6.html @@ -0,0 +1,705 @@ + + + + + + Data structures, writing CSV files & wrap-up + + + + + + + + +
    +
    + +
    +

    The grand finale!
    Data structures, writing CSV files & wrap-up

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + + +
    +

    Class outline:

    + +
      +
    • Review +
    • Tuples +
    • Dictionaries +
    • Writing CSV files +
    • Putting it all together +
    • Where to go from here? +
    +
    +
    +

    Review

    +
    +
    +

    Checking if value is in a list

    + +

    The in keyword checks if + a value is in a list (or any sequence).

    + +
    
    +                    if "bananas" in groceries:
    +                        print("Watch your step!")
    +
    +                    if "bleach" in groceries:
    +                        print("Watch what you eat!")
    +                    
    + +

    When used inside if conditions, in expressions return a Boolean (True/False).

    +
    +
    +

    Helpful list methods

    + + + + + + + + +
    Method + Description +
    count(item) + Returns the number of occurrences of item in the list. If item is not found, returns 0. +
    reverse() + Reverses the elements of the list in place. +
    sort([key=function]) + Sorts the items of the list in place. The optional key argument specifies + a function to compute a comparison key for each item in the list. Otherwise, items are compared based on their values. +
    + +

    For more about list methods, seePython.org documentation

    +
    +
    +

    Useful built-in functions for lists

    + +

    These are functions, not methods.

    + + + + + + + + +
    Module + Function + Description +
    Global + min(list, [key=function]) + Returns the minimum value in list. The optional key argument specifies a custom comparator function. +
    Global + max(list, [key=function]) + Returns the maximum value in list. he optional key argument specifies a custom comparator function. +
    random + choice(list) + Returns a randomly selected item from list. +
    random + shuffle(list) + Shuffles the elements of the list in place. +
    +

    For more on built-in functions see Python.org documentation. Functions that work with lists are those that accept an "iterable" as an argument.

    +
    +
    +

    Nested Lists

    + +

    Since Python lists can contain any values, an item can itself be a list.

    + +
    +                    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2], # gymnasts[0]
    +                                    ["Lea", 9, 8.8, 9.1, 9.5], # gymnasts[1]
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8] # gymnasts[2]
    +                               ]
    +                    
    +

    You can think of nested lists like rows in a table:

    + +
    +
    +

    Accessing nested list items

    + +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    + +

    Access using bracket notation, with more brackets as needed:

    +
    
    +                    gymnasts[0]    # ["Brittany", 9.15, 9.4, 9.3, 9.2]
    +                    gymnasts[0][0] # "Brittany"
    +                    gymnasts[1][0] # "Lea"
    +                    gymnasts[1][4] # 9.5
    +                    gymnasts[1][5] # 🚫 IndexError!
    +                    gymnasts[3][0] # 🚫 IndexError!
    +                    
    +
    +
    +

    Modifying nested lists: Bracket notation

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    +

    Modify using bracket notation as well, just like before:

    +
    
    +                    gymnasts[0] = ["Olivia", 8.75, 9.1, 9.6, 9.8]
    +                    gymnasts[1][0] = "Leah"
    +                    gymnasts[2][4] = 9.8
    +                    
    +
    +
    +

    Modifying nested lists: List methods

    +

    If we start with...

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5]
    +                               ]
    +                    
    +

    We can append another list a few ways:

    +
    
    +                    gymnasts.append(["Maya", 9.2, 8.7, 9.2, 8.8])
    +                    
    +
    
    +                    gymnast = []
    +                    gymnast.append("Maya")
    +                    gymnast.append(9.2)
    +                    gymnast.append(8.7)
    +                    gymnast.append(9.2)
    +                    gymnast.append(8.8)
    +                    gymnasts.append(gymnast)
    +                    
    +
    + +
    +

    Looping through nested lists

    +
    
    +                    gymnasts = [
    +                                    ["Brittany", 9.15, 9.4, 9.3, 9.2],
    +                                    ["Lea", 9, 8.8, 9.1, 9.5],
    +                                    ["Maya", 9.2, 8.7, 9.2, 8.8]
    +                                ]
    +                    
    +

    Use a nested for-in loop:

    +
    
    +                    for gymnast in gymnasts:
    +                        print(gymnast)
    +                        for data in gymnast:
    +                            print(data)
    +                    
    +

    Remember what type of data is being stored in the loop variable!

    +
    +
    +

    CSV files

    +

    Comma Separated Value (CSV) is a plain text format used to store "tabular" data (aka rows and columns), like from a spreadsheet or database table.

    +

    Because CSV is simple and non-proprietary, it's commonly used to exchange data between different applications.

    +
    
    +                        Brittany, 9.15, 9.4, 9.3, 9.2
    +                        Lea, 9, 8.8, 9.1, 9.5
    +                        Maya, 9.2, 8.7, 9.2, 8.8
    +                    
    + +
    +
    +

    Opening files

    +

    We use the Python built in open() method to open files for reading or writing.

    +

    The keyword with tells Python to automatically close the file when we're finished.

    +
    
    +                        with open('filename') as my_file:
    +                            # do something
    +                    
    +

    See the docs on python.org for more

    +
    +
    +

    Reading files with CSV module

    +

    Python has a built-in CSV module that includes many features used for reading/writing CSV files.

    + Open a CSV and read its contents (docs at python.org) +
    
    +                        # import the csv module
    +                        import csv
    +                        # open the file
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            # load the contents of the CSV file into a variable
    +                            csv_reader = csv.reader(my_file)
    +                            # CSV is a nested list!
    +                            # now we can loop through the rows in the file
    +                            for row in csv_reader:
    +                                print(row)
    +                    
    +
    +
    +

    Reading files with CSV module

    +

    A CSV is a list of rows, which are lists of values.

    +

    We can use nested for loops to get values from rows and cells.

    +
    
    +                        import csv
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            csv_reader = csv.reader(my_file, delimiter=',')
    +                            for row in csv_reader:
    +                                print(row)
    +                                for cell in row:
    +                                    print(cell)
    +                    
    +
    +
    +

    Homework review!

    +

    Repl: Class4Ex5NestedForLoops

    +
    +
    +

    More data structures!

    +
    + +
    +

    Tuples

    + +

    A tuple is like a list, but immutable: its values cannot be changed after the initialization.

    +

    Tuples are enclosed in parentheses (9.99, 7.99, 3.99)

    + + +
    
    +                    position = (100, 50)
    +                    prices = (9.99, 7.99, 3.99)
    +                    
    + +

    You can still access items in a tuple:

    +
    
    +                    position = (100, 50)
    +                    x = position[1]
    +                    y = position[2]
    +                    
    + +

    Or iterate through:

    +
    
    +                    total = 0
    +                    for price in prices:
    +                        total += price
    +                    
    +
    + +
    +

    Tuple immutability

    + +

    All of these operations will result in an error:

    + +
    
    +                    position = (100, 50)
    +
    +                    position[0] = 50
    +                    position[1] = 10
    +                    position.append(10)
    +                    
    + +

    When to use tuples?

    + +

    When you have list that won't change as your program runs. Tuples are much more memory efficent than lists. Your code will run much faster!

    + +
    +
    +

    Dictionaries

    +

    A dict is a mutable mapping of key-value pairs

    +
    
    +					states = {
    +						"CA": "California",
    +						"DE": "Delaware",
    +						"NY": "New York",
    +						"TX": "Texas",
    +						"WY": "Wyoming"
    +					}
    +					
    +

    Dictionaries allow you to access values using a human-readable name ("key") rather than an index number. Dictionaries map very well to JSON!

    +
    +
    +

    Dictionary Class1Ex1OperatorExpressions

    +
    
    +					>>> len(states)
    +					5
    +					
    +
    
    +					>>> "CA" in states
    +					True
    +					
    +
    
    +					>>> "ZZ" in states
    +					False
    +					
    + +
    +
    +

    Dictionary selection

    +
    
    +					words = {
    +						"mΓ‘s": "more",
    +						"otro": "other",
    +						"agua": "water"
    +					}
    +					
    +

    Select a value:

    +
    
    +					>>> words["otro"]
    +					'other'
    +					
    +
    
    +					>>> first_word = "agua"
    +					>>> words[first_word]
    +					'water'
    +					
    +
    
    +					>>> words["pavo"]
    +					KeyError: pavo
    +					
    +
    +
    +

    Dictionary mutation

    +

    Create an empty dict:

    +
    
    +					users = {}
    +					
    +

    Add values:

    +
    
    +					users["liz"] = "b3stp@ssEvErDontHackMe"
    +					
    +

    Change values:

    +
    
    +					users["liz"] = "itsLongerSoItsMoreSecure!!"
    +					
    +
    
    +					>>> users["liz"]
    +					'itsLongerSoItsMoreSecure!!'
    +					
    +
    + +
    +

    Dictionary rules

    +
      +
    • A key cannot be a list or dictionary (or any mutable type)
    • +
    • All keys in a dictionary are distinct (there can only be one value per key)
    • +
    • The values can be any type, however!
    • +
    +
    
    +					spiders = {
    +					  "smeringopus": {
    +						  "name": "Pale Daddy Long-leg",
    +						  "length": 7
    +					  },
    +					  "holocnemus pluchei": {
    +						  "name": "Marbled cellar spider",
    +						  "length": (5, 7)
    +					  }
    +					}
    +					
    +
    +
    +

    Dictionary iteration

    +
    
    +					insects = {"spiders": 8, "centipedes": 100, "bees": 6}
    +                    for insect in insects:
    +                        print("Key is " + insect)
    +                        # ex insects['spiders']
    +                        print("Value is " + str(insects[insect]))
    +					
    +

    What will be the order of items?

    +
    
    +					8 100 6
    +					
    +

    Keys are iterated over in the order they are first added.

    +
    +
    +

    Dictionary iteration: A short-hand way

    +

    The .items() dictionary method returns a list containing a tuple for each key/value pair

    +
    
    +					insects = {"spiders": 8, "centipedes": 100, "bees": 6}
    +                    for key, value in insects.items()
    +                        print("Key is " + key)
    +                        print("Value is " + str(value))
    +					
    +

    More dictionary methods

    +
    +
    +

    Exercise: Dictionaries

    + + +
    +
    +

    Reading CSV files as dictionaries

    +
    +
    +

    Reading CSV files with headers

    +

    Python has a built-in CSV module that includes many features used for reading/writing CSV files.

    + Open a CSV and read its contents +
    
    +                        # import the csv module
    +                        import csv
    +                        # open the file
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            # load the contents of the CSV file into a variable
    +                            csv_reader = csv.DictReader(my_file)
    +                            # CSV is read as a dictionary with column headers as keys!
    +                            # now we can loop through the rows in the file
    +                            # and get the values from specific columns
    +                            for row in csv_reader:
    +                                print(row)
    +                    
    +
    +
    +

    Exercise: CSV with headers

    +

    Let's re-visit our gradebook exercise...

    + +
    +
    +

    Writing CSV files

    +
    +
    +

    Writing files with CSV module

    +

    Python's built-in CSV module also has support for writing files (docs at python.org) +

    
    +                        # import the csv module
    +                        import csv
    +                        my_list = [
    +                                ["Mon", "Oatmeal", "Salad", "Pasta"],
    +                                ["Tues", "Waffles", "Soup", "Tacos"],
    +                                ["Wed", "Cereal", "Sandwich", "Pizza"]
    +                            ]
    +                        # open a new or existing file for writing
    +                        with open('fun_spreadsheet.csv', 'w') as my_file:
    +                            # prepare the CSV for writing
    +                            writer = csv.writer(my_file)
    +                            # write data from a list to the CSV file
    +                            writer.writerows(my_list)
    +                    
    +
    +
    +

    Putting it all together

    +
    +
    +

    We learned so much!

    + +
      +
    • Data types/expressions +
    • Variables +
    • Functions +
    • Conditionals (if/else) +
    • Loops (while, for/in) +
    • Data structures (lists, tuples, dictionaries) +
    • Reading/writing CSV files +
    +
    +
    +

    Wrap-up project: Pizza order

    +

    Let's put it all together in one final exercise!

    +

    Repl: Class6Ex3PizzaOrder

    +
    + +
    +

    What's next?! πŸŽ‰ 🐍

    +
    +
    +

    Learning opps

    +
  • GDI Python 2 Cohort (next session June 13-29) +
  • Self-paced learning: Real Python tutorials are great +
  • Check your local community college - most offer online Python and other programming courses +
  • +
    +

    Learning opps: Coursera courses

    +
  • University of MI Python for Everybody +
  • University of MI Python 3 Programming +
  • Google IT Automation with Python Certificate +
  • +
    +

    But really, you need to practice coding!

    +

    Hands-on project ideas:

    + +
    +
    +

    Next topics to explore

    +
      +
    • Error handling +
    • Working with files +
    • Getting data from APIs/databases +
    • Installin Python on your computer & managing Python packages with PIP +
    +
    + +
    +

    Building Python web apps

    +

    Frameworks like Django and Flask are commonly used to build web apps quickly

    + +
    + +
    +

    Feedback survey

    + +

    Please fill out the GDI feedback survey + to help us improve future classes. Thanks!

    +
    + +
    +
    + + + + + + + + + diff --git a/deloitte-python-1-aug-2022/images/advanced-search.png b/deloitte-python-1-aug-2022/images/advanced-search.png new file mode 100644 index 0000000..cd3ca64 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/advanced-search.png differ diff --git a/deloitte-python-1-aug-2022/images/call_expression_anatomy.png b/deloitte-python-1-aug-2022/images/call_expression_anatomy.png new file mode 100644 index 0000000..38b8155 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/call_expression_anatomy.png differ diff --git a/deloitte-python-1-aug-2022/images/console_application.png b/deloitte-python-1-aug-2022/images/console_application.png new file mode 100644 index 0000000..16b2149 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/console_application.png differ diff --git a/deloitte-python-1-aug-2022/images/create-repl.png b/deloitte-python-1-aug-2022/images/create-repl.png new file mode 100644 index 0000000..069dce8 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/create-repl.png differ diff --git a/deloitte-python-1-aug-2022/images/desktop_application.png b/deloitte-python-1-aug-2022/images/desktop_application.png new file mode 100644 index 0000000..b0a6a00 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/desktop_application.png differ diff --git a/deloitte-python-1-aug-2022/images/envdiagram_names_global.png b/deloitte-python-1-aug-2022/images/envdiagram_names_global.png new file mode 100644 index 0000000..c60371f Binary files /dev/null and b/deloitte-python-1-aug-2022/images/envdiagram_names_global.png differ diff --git a/deloitte-python-1-aug-2022/images/envdiagram_names_in_func.png b/deloitte-python-1-aug-2022/images/envdiagram_names_in_func.png new file mode 100644 index 0000000..8c163f7 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/envdiagram_names_in_func.png differ diff --git a/deloitte-python-1-aug-2022/images/first_bug.jpg b/deloitte-python-1-aug-2022/images/first_bug.jpg new file mode 100644 index 0000000..0379237 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/first_bug.jpg differ diff --git a/deloitte-python-1-aug-2022/images/global.png b/deloitte-python-1-aug-2022/images/global.png new file mode 100644 index 0000000..d3f3c46 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/global.png differ diff --git a/deloitte-python-1-aug-2022/images/if-order.png b/deloitte-python-1-aug-2022/images/if-order.png new file mode 100644 index 0000000..6eef13b Binary files /dev/null and b/deloitte-python-1-aug-2022/images/if-order.png differ diff --git a/deloitte-python-1-aug-2022/images/if-order2.png b/deloitte-python-1-aug-2022/images/if-order2.png new file mode 100644 index 0000000..39b819b Binary files /dev/null and b/deloitte-python-1-aug-2022/images/if-order2.png differ diff --git a/deloitte-python-1-aug-2022/images/legb.png b/deloitte-python-1-aug-2022/images/legb.png new file mode 100644 index 0000000..86dbafc Binary files /dev/null and b/deloitte-python-1-aug-2022/images/legb.png differ diff --git a/deloitte-python-1-aug-2022/images/list.png b/deloitte-python-1-aug-2022/images/list.png new file mode 100644 index 0000000..33e1bda Binary files /dev/null and b/deloitte-python-1-aug-2022/images/list.png differ diff --git a/deloitte-python-1-aug-2022/images/local.png b/deloitte-python-1-aug-2022/images/local.png new file mode 100644 index 0000000..a8bcdf9 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/local.png differ diff --git a/deloitte-python-1-aug-2022/images/name_value.png b/deloitte-python-1-aug-2022/images/name_value.png new file mode 100644 index 0000000..60cd9c1 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/name_value.png differ diff --git a/deloitte-python-1-aug-2022/images/nested-lists-table.png b/deloitte-python-1-aug-2022/images/nested-lists-table.png new file mode 100644 index 0000000..3edaa9d Binary files /dev/null and b/deloitte-python-1-aug-2022/images/nested-lists-table.png differ diff --git a/deloitte-python-1-aug-2022/images/nested_expression_tree.png b/deloitte-python-1-aug-2022/images/nested_expression_tree.png new file mode 100644 index 0000000..1da6a94 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/nested_expression_tree.png differ diff --git a/deloitte-python-1-aug-2022/images/notebook.png b/deloitte-python-1-aug-2022/images/notebook.png new file mode 100644 index 0000000..e83415d Binary files /dev/null and b/deloitte-python-1-aug-2022/images/notebook.png differ diff --git a/deloitte-python-1-aug-2022/images/postman-fork.png b/deloitte-python-1-aug-2022/images/postman-fork.png new file mode 100644 index 0000000..d0df118 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/postman-fork.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_assignment.png b/deloitte-python-1-aug-2022/images/pythontutor_assignment.png new file mode 100644 index 0000000..61c7fe5 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_assignment.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_code.png b/deloitte-python-1-aug-2022/images/pythontutor_code.png new file mode 100644 index 0000000..fb59a4d Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_code.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_code2.png b/deloitte-python-1-aug-2022/images/pythontutor_code2.png new file mode 100644 index 0000000..31ad29a Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_code2.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_conditionals.png b/deloitte-python-1-aug-2022/images/pythontutor_conditionals.png new file mode 100644 index 0000000..9b8e9b3 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_conditionals.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_defstatement.png b/deloitte-python-1-aug-2022/images/pythontutor_defstatement.png new file mode 100644 index 0000000..fb1ec8a Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_defstatement.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_frames.png b/deloitte-python-1-aug-2022/images/pythontutor_frames.png new file mode 100644 index 0000000..58fd292 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_frames.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_frames2.png b/deloitte-python-1-aug-2022/images/pythontutor_frames2.png new file mode 100644 index 0000000..54957c8 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_frames2.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_functioncall.png b/deloitte-python-1-aug-2022/images/pythontutor_functioncall.png new file mode 100644 index 0000000..9d906ef Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_functioncall.png differ diff --git a/deloitte-python-1-aug-2022/images/pythontutor_loops.png b/deloitte-python-1-aug-2022/images/pythontutor_loops.png new file mode 100644 index 0000000..7bc0e45 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/pythontutor_loops.png differ diff --git a/deloitte-python-1-aug-2022/images/replit-edit-in-workspace.png b/deloitte-python-1-aug-2022/images/replit-edit-in-workspace.png new file mode 100644 index 0000000..bcfdd7b Binary files /dev/null and b/deloitte-python-1-aug-2022/images/replit-edit-in-workspace.png differ diff --git a/deloitte-python-1-aug-2022/images/replit-fork.png b/deloitte-python-1-aug-2022/images/replit-fork.png new file mode 100644 index 0000000..3d7ae95 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/replit-fork.png differ diff --git a/deloitte-python-1-aug-2022/images/table.png b/deloitte-python-1-aug-2022/images/table.png new file mode 100644 index 0000000..3fa43df Binary files /dev/null and b/deloitte-python-1-aug-2022/images/table.png differ diff --git a/deloitte-python-1-aug-2022/images/web_application.png b/deloitte-python-1-aug-2022/images/web_application.png new file mode 100644 index 0000000..3a3acf4 Binary files /dev/null and b/deloitte-python-1-aug-2022/images/web_application.png differ diff --git a/deloitte-python-1-aug-2022/index.html b/deloitte-python-1-aug-2022/index.html new file mode 100644 index 0000000..8614c80 --- /dev/null +++ b/deloitte-python-1-aug-2022/index.html @@ -0,0 +1,167 @@ + + + + + + GDI Python 1 + + + +
    + + +
    + +
    +

    + Lesson 1: Intro to Python +

    + +

    Topics:

    +

    Data types, expressions, values, names

    + +

    Materials:

    + +
    + +
    +

    + Lesson 2: Functions +

    + +

    Topics:

    +

    User-defined functions, namespaces

    + +

    Materials:

    + +
    + +
    +

    + Lesson 3: Conditionals & Loops +

    + +

    Topics:

    +

    Boolean expressions, conditionals (if/elif/else), loops intro

    + +

    Materials:

    + +
    + +
    +

    + Lesson 4: Loops (continued) + data structures +

    +

    Topics:

    +

    Lists, list methods, for loops, nested lists

    + +

    Materials:

    + +
    + +
    +

    + Lesson 5: More list functionality, Nested lists (continued), Reading data from CSV files +

    + +

    Topics:

    +

    More list functionality, tuples, dictionaries

    +

    Materials:

    +

    Coming soon!

    + +
    + + +
    + +
    +

    + Lesson 6: More data structures, CSV files & wrap-up +

    + +

    Topics:

    +

    Tuples, dictionaries, writing to CSV files, learning resources

    + +

    Materials:

    + +
    + +
    + +
    + + diff --git a/deloitte-python-2-jan-2023/README.md b/deloitte-python-2-jan-2023/README.md new file mode 100644 index 0000000..632ef49 --- /dev/null +++ b/deloitte-python-2-jan-2023/README.md @@ -0,0 +1,27 @@ +# Girl Develop It Python 2 Class, Jan/Feb 2023 + +## Overview +This course is a special series customized for the Deloitte WinC (Women in Computing) group. It's based on the standard GDI Python 2 curriculum, but adjusted for the interests of the group, which included working with APIs and building web apps with frameworks. + +This course builds on the basics covered in Python 1 and includes more advanced topics, such as: + +- File input/output +- List comprehension +- Error handling +- Argument parsing +- Making HTTP requests/handling responses +- Building web apps with frameworks (Django) + +We'll also touch on object-oriented Python and the popular Python web application framework, Django. + +This class series consists of 6 2-hr sessions: + +- [Class 7](https://github.com/lizkrznarich/gdi-python-2/tree/main/class7): Review from Python 1 & more reading/writing files +- [Class 8](https://github.com/lizkrznarich/gdi-python-2/tree/main/class8): More file operations, argument parsing & list comprehension +- [Class 9](https://github.com/lizkrznarich/gdi-python-2/tree/main/class9): Error handling +- [Class 10](https://github.com/lizkrznarich/gdi-python-2/tree/main/class10): HTTP requests +- [Class 11](https://github.com/lizkrznarich/gdi-python-2/tree/main/class11): Intro to Python frameworks & object-oriented Python +- [Class 12](https://github.com/lizkrznarich/gdi-python-2/tree/main/class12): Your own app with Django! + +## Using slides +Slides are in HTML - access them at the links above, or download this repository to your computer and open the classX.html file inside each classX folder in a browser (ex: [class7/class7.html](https://github.com/lizkrznarich/gdi-python-2/blob/main/class7/class7.html)) diff --git a/deloitte-python-2-jan-2023/class10/class10.html b/deloitte-python-2-jan-2023/class10/class10.html new file mode 100644 index 0000000..3890381 --- /dev/null +++ b/deloitte-python-2-jan-2023/class10/class10.html @@ -0,0 +1,707 @@ + + + + + + HTTP requests & JSON + + + + + + + + +
    +
    + +
    +

    HTTP requests & JSON

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + + +
    +

    Class outline:

    + +
      +
    • Review +
    • HTTP basics +
    • Making GET requests +
    • Parsing JSON responses +
    • Handling HTTP exceptions +
    +
    +
    +

    Review: Errors & exception handling

    +
    +
    +

    Types of errors

    + +

    These are common to all programming languages:

    +
      +
    • Syntax errors
    • +
    • Logic errors
    • +
    • Runtime errors
    • +
    +
    +
    +

    Syntax errors

    +
    +
    +

    Common syntax errors

    +
      +
    • Extra or missing parenthesis +
    • Missing colon at the end of an if, while, def statements, etc. +
    • Missing/unmatched quotes +
    • Incorrect/misaligned indents +
    +

    + +

    To fix a syntax error, read the message carefully and go through your code with a critical eye. πŸ‘
    + ...and lint your code!

    + +
    + +
    +

    Linting

    + +

    To avoid syntax errors, use a linting tool to check your code as you write it. Many IDEs have a Python linter built in or available as an extension (ex: VSCode Python linting).

    + +

    You can also run Pylint on your code

    + +
    
    +                    # import pylint
    +                    # Already installed in Replit - no import needed
    +                    def sum(a, b):
    +                        total = a + b
    +                    return total
    +                    
    +

    In Replit, switch to the Shell tab and type pylint main.py and press Enter.
    + When prompted to select a version, press Enter again.

    +
    +
    +

    Logic errors

    + +

    A program has a logic error if it does not behave as expected. + Typically discovered via failing tests or bug reports from users. +

    + +

    Spot the logic error:

    +
    
    +                    # Which medal goes to the first place winner?
    +                    medals = ["gold", "silver", "bronze"]
    +                    first_place = medals[1]
    +                    print(first_place)
    +                    
    +

    To avoid the wrath of angry users due to logic errors, write tests!

    +
    +
    +

    Testing

    + +

    There are several Python testing frameworks. Pytest is a good one to start with.

    + +
    
    +                    import pytest
    +
    +                    medals = ["gold", "silver", "bronze"]
    +                    def get_medal(place):
    +                        return medals[place]
    +
    +                    def test_get_medal():
    +                        assert get_medal(1) == "gold"
    +                    
    +

    In Replit, click Run to install Pytest, then switch to the Shell tab and type pytest main.py and press Enter.

    +
    +
    +

    Runtime errors

    +

    Even with testing and linting, errors can slip through!

    +

    A runtime error happens while a program is running, + often halting the execution of the program. +

    + +

    Spot the runtime error:

    +
    
    +                    def div_numbers(dividend, divisor):
    +                        return dividend/divisor
    +
    +                    quot1 = div_numbers(10, 2)
    +                    quot2 = div_numbers(10, 1)
    +                    quot3 = div_numbers(10, 0)  # Cannot divide by 0!
    +                    quot4 = div_numbers(10, -1)
    +                    
    + +

    To prevent runtime errors, code defensively and write tests for all edge cases.

    +
    +
    +

    Tracebacks

    + +

    When there's a runtime error in your code, + you'll see a traceback in the console.

    + +
    
    +                        def div_numbers(dividend, divisor):
    +                            return dividend/divisor
    +
    +                        quot1 = div_numbers(10, 2)
    +                        quot2 = div_numbers(10, 1)
    +                        quot3 = div_numbers(10, 0)
    +                        quot4 = div_numbers(10, -1)
    +                    
    + +
    
    +                    Traceback (most recent call last):
    +                        File "main.py", line 14, in <module>
    +                            quot3 = div_numbers(10, 0)
    +                        File "main.py", line 10, in div_numbers
    +                            return dividend/divisor
    +                    ZeroDivisionError: division by zero
    +                    
    +
    +
    +

    Exceptions

    + +

    Python raises an exception whenever a runtime error occurs. + An exception is a mechanism in many languages used to declare and respond to "exceptional" conditions.

    + +

    How an exception is reported:

    +
    
    +                    >>> 10/0
    +                    Traceback (most recent call last):
    +                        File "<stdin>", line 1, in 
    +                    ZeroDivisionError: division by zero
    +                    
    + +

    If an exception is not handled, the program stops executing immediately.

    +
    +
    +

    The try statement

    + +

    To handle an exception (keep the program running), use a try statement.

    + +
    
    +                    try:
    +                        <code you want to run if all goes well>
    +                    except:
    +                        <code you want to run if this particular exception happens>
    +                       ...
    +                    
    + +

    The <try statement> is executed first. + If and exception is raised with the <try statement> executes, + the <except statement> is executed. +

    +
    +
    +

    Try statement example

    + +
    
    +                    try:
    +                        quot = 10/0
    +                    except:
    +                        print("An error happened")
    +                        quot = 0
    +                    
    +
    + +
    +

    Getting error details

    +

    To get the error message that Python returned, we need to catch the Exception and assign it to a variable.

    +
    
    +                    try:
    +                        quot = 10/0
    +                    except Exception as e:
    +                        print('Handling an error:', e)
    +                        quot = 0
    +                    
    +
    +
    +

    Default Exception

    +

    All exception types are derived from the parent class Exception.

    +
      +
    • Exception can be used as a wildcard that catches (almost) everything
    • +
    • It can be used on its own, or as a last resort to catch exceptions that you haven't caught with a more specific type
    • +
    +
    +
    +

    Types of exceptions

    + +

    A few exception types and examples of buggy code:

    + + + + + + + + +
    Exception + Example +
    TypeError + 'hello'[1] = 'j' +
    IndexError + 'hello'[7] +
    NameError + x += 5 +
    FileNotFoundError + open('dsfdfd.txt') +
    + +

    See full list in the exceptions docs. Note: Third party Python packages often include their own custom exception types!

    + +
    +
    +

    Catching a specific exception type

    +

    In some cases, we need to catch and handle specific exceptions. Multiple except statements that catch different exception types are allowed. It's a best practice to catch the default Exception, in addition to specific types.

    +
    
    +                    try:
    +                        quot = 10/0
    +                    except ZeroDivisionError as e:
    +                        print('Handling zero division exception:', e)
    +                        quot = 0
    +                    except Exception as e:
    +                        print('Something else went wrong:', e)
    +                    
    +
    +
    +

    Try inside a function

    +
    
    +                    def div_numbers(dividend, divisor):
    +                        try:
    +                            quotient = dividend/divisor
    +                        except ZeroDivisionError as e:
    +                            print('Handling zero division exception:', e)
    +                            quotient = 0
    +                        except Exception as e:
    +                            print('Something else went wrong:', e)
    +                            quotient = None
    +                        return quotient
    +
    +                    div_numbers(10, 2)
    +                    div_numbers(10, 0)
    +                    div_numbers(10, 'foo')
    +                    
    +

    Depending on the case, we may want to place the return statement inside the try statement, so that there is only a return value if the code succeeds.

    +
    +
    +

    System Exit

    +

    To stop the program if a certain exception is encountered, move the return statement inside the try statement and raise a SystemExit() inside the except statement. +

    
    +                    def div_numbers(dividend, divisor):
    +                        try:
    +                            quotient = dividend/divisor
    +                        except ZeroDivisionError as e:
    +                            print('Encountered error:', e)
    +                            quotient = 0
    +                        except Exception as e:
    +                            print('Something else went wrong:', e)
    +                            raise SystemExit()
    +                        return quotient
    +
    +                    div_numbers(10, 2)
    +                    div_numbers(10, 0)
    +                    div_numbers(10, -1)
    +                    
    +
    +
    +

    Raising custom exceptions

    +

    You can raise an exception and cause the program to stop, even if there's no problem that Python encounters.
    + This is helpful when your program requires certain values or conditions in order to work properly.

    +
    
    +                    x = 10
    +                    if x > 5:
    +                        raise Exception("x cannot exceed 5")
    +                    
    +
    +
    +

    Exercise review:

    + +
    +
    +

    HTTP basics

    +
    +
    +

    What is HTTP?

    +

    Hypertext Transfer Protocol (HTTP) is how we send data and files around the Web

    +

    HTTP works as a request-response protocol between a client and server.

    +
      +
    • Client could be a web browser (operated by a human) or an application (like a computer running a Python program)
    • +
    • Server could be a computer with files (like HTML) stored on it, or an application serving up data through an API
    • +
    +
    +
    +

    HTTP requests

    +

    An HTTP request consists of:

    +
      +
    1. Method (required) GET, PUT, POST, etc
    2. +
    3. Request URI (required) Full URI, including any query parameters
    4. +
    5. Header(s) (optional) Ex: API token)
    6. +
    7. Body (optional) Ex: data you want to send
    8. +
    +
    
    +                        curl # Command-line tool used to send HTTP requests
    +                        -X GET # Method
    +                        -H 'Accept: application/json' # Header
    +                        # Request URI
    +                        'https://api.open-meteo.com/v1/forecast?latitude=43.07&longitude=-89.40&hourly=temperature_2m'
    +                    
    +
    +
    +

    HTTP requests

    +

    Common request methods

    + + + + + + + +
    GETRetreive data from a specified resource
    POSTSend data to a server (usually via an API) to create/overwrite a resource
    PUTSend data to a server (usually via an API) to create/update a resource
    DELETEDelete a specified resource
    +
    +
    +

    Why do we care about HTTP requests?

    +

    APIs! We communicate with and integrate other software and services into our apps via APIs. Many web services offer APIs:

    +
      +
    • Google (many APIs for different services)
    • +
    • AWS (and other cloud compute providers)
    • +
    • Salesforce (and other CRMs)
    • +
    • Github (and other dev tools) +
    • Social media & email marketing platforms
    • +
    +

    Python is a great language for working with APIs!

    +
    +
    +

    Making HTTP requests

    +
    +
    +

    Requests module

    +

    The Requests module is a third-party library, + and is the de-facto standard for sending HTTP requests and receiving responses using Python.

    +

    On your own machine, you need to install requests before you can import it into Python files

    +
    
    +                        pip install requests
    +                    
    +

    Requests module documentation

    +
    +
    +

    Requests module

    +

    In Replit, install requests by clicking Tools > Packages, then searching for "requests"

    + +
    +
    +

    Making a GET request

    +

    requests.get() sends an HTTP request and returns an HTTP response object

    +
    
    +                        import requests
    +                        response = requests.get("https://girldevelopit.com")
    +                        print(vars(response))
    +                    
    +
    +
    +

    What's in a Response?

    +

    Lots of stuff! See full list. The values we're typically concerned about are: + + + + + + +
    .status_codeStatus code of the request (200 OK, 404 Not found, etc)
    .text, .json or .rawBody of the response (stored in different attributes, depending on the type of response
    .headersHTTP response headers, with details about the response content and where it came from
    +

    +
    +

    What's in a Response?

    +

    Let's look at some response values

    +
    
    +                            import requests
    +
    +                            response = requests.get("https://girldevelopit.com")
    +                            print(response.status_code) # HTTP status code (200)
    +                            print(response.headers) # Content-type tells us what kind of response this is (text/html)
    +                            print(response.text) # The full body of the response (HTML, in this case)
    +                        
    +
    +
    +

    Working with APIs

    +
    +
    +

    What's an API?

    +

    An Application Programming Interface (API) is a way for 2 separate computer systems to communicate. Essentially, it's a set of rules for retrieving, creating, updating and/or deleting data in another system.

    +

    There are many different types of APIs, but on the Web we're typically talking about RESTful APIs, which allow 2 applications to exchange data securely over the Internet. RESTful APIs use URIs to identify resources.

    +
    +
    +

    How do APIs work?

    +

    Most Web APIs accept HTTP requests and return JSON responses (more on that in a moment!).

    +

    Beyond that, each API has it's own rules for:

    +
      +
    • What resources are available
    • +
    • Which methods are allowed (GET, PUT, POST, DELETE)
    • +
    • Which headers are allowed/required
    • +
    • Which query parameters are allowed/required
    • +
    • What type of authentication is required (if any)
    • +
    +

    Check the documentation for the API you're interested. Here's a list of free APIs to get you started!

    +
    +
    +

    The NASA APOD API

    +

    NASA posts an Astronomy Picture of the Day each day, which is also available via an API. To use this API, you first need to register for a key at https://api.nasa.gov

    + +
    +
    +

    The NASA APOD API

    +

    After registering, you should recieve a key, along with a sample request.

    + +
    +
    +

    Query parameters

    +

    In the NASA API, your key is added as a query paramter

    +
    
    +                        ?api_key=eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn&start_date=2023-01-01
    +                    
    +

    Query parameters ("params") are key/value pairs that allow adding extra context to a URL.

    +
      +
    • Query param portion of a URL begins with ?
    • +
    • Each additional param is preceded with &
    • +
    +
    
    +                        https://api.nasa.gov/planetary/apod?api_key=eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn&start_date=2023-01-01
    +                    
    +

    Params are specific to seach site/app/API - there's no universal set of available params

    +
    +
    +

    The NASA APOD API

    +

    Let's run this in Python

    +
    
    +                        import requests
    +
    +                        # per NASA API docs, we need to pass the key as a query parameter
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
    +                        print(response.status_code)
    +                        print(response.headers)
    +                    
    +
    + +
    +

    Parsing JSON responses

    +
    +
    +

    About JSON

    +

    Javascript Object Notation (JSON) is an open standard file format that stores data in key/value pairs. It looks a lot like a Python dictionary!

    +

    Requests has a built-in .json() method for parsing JSON responses, and Python has a built-in JSON library, too.

    +
    
    +                        import requests
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
    +                        print(response.json())
    +                    
    +
    +
    +

    JSON example

    + +
    
    +                        {
    +                            'copyright': 'Mike Selby',
    +                            'date': '2023-02-04',
    +                            'explanation': 'Centered in this colorful cosmic canvas, NGC 2626 is a beautiful, bright, blue reflection nebula in the southern Milky Way. Next to an obscuring dust cloud and surrounded by reddish hydrogen emission from large H II region RCW 27 it lies within a complex of dusty molecular clouds known as the Vela Molecular Ridge. NGC 2626 is itself a cloud of interstellar dust reflecting blue light from the young hot embedded star visible within the nebula. But astronomical explorations reveal many other young stars and associated nebulae in the star-forming region. NGC 2626 is about 3,200 light-years away. At that distance this telescopic field of view would span about 30 light-years along the Vela Molecular Ridge.',
    +                            'hdurl': 'https://apod.nasa.gov/apod/image/2302/NGC_2626_CDK_700_II_20_Jan_2023.jpg',
    +                            'media_type': 'image',
    +                            'service_version': 'v1',
    +                            'title': 'NGC 2626 along the Vela Molecular Ridge',
    +                            'url': 'https://apod.nasa.gov/apod/image/2302/NGC_2626_CDK_700_II_20_Jan_2023_1024.jpg'
    +                        }
    +                    
    +
    +
    +

    Accessing JSON values

    +

    Once the response values are parsed as JSON, we can treat it like a dictionary and access individual fields with bracket notation.

    +
    
    +                        import requests
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
    +                        url = response['url']
    +                        print(url)
    +                    
    +
    +
    +

    Handling HTTP errors

    +
    +
    +

    HTTP status exceptions

    +

    Requests includes custom exception types, such as HTTP error, which covers issues like 404 not found and 403 access denied (bad credentials).

    +

    Requests does not automatically raise HTTP exceptions; we need to do that explicitly with the .raise_for_status() method and handle the exception.

    +
    +
    +

    Handling HTTP errors

    +
    
    +                        import requests
    +
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +
    +                        try:
    +                            response = requests.get("https://api.nasa.gov/planetary/apo", params=params)
    +                            response.raise_for_status()
    +                            url = response['url']
    +                            print(url)
    +                        except requests.exceptions.HTTPError as e:
    +                            print("Oh no, an error happened: ", e)
    +                    
    +
    +
    +

    Exercise: Requests

    +

    Let's play with the NASA APOD API!

    +

    Class10Ex1Requests

    +
    +
    +
    + Ex1 + + + + + + + diff --git a/deloitte-python-2-jan-2023/class11/class11.html b/deloitte-python-2-jan-2023/class11/class11.html new file mode 100644 index 0000000..b63fbb1 --- /dev/null +++ b/deloitte-python-2-jan-2023/class11/class11.html @@ -0,0 +1,472 @@ + + + + + + Intro to Python frameworks & Django setup + + + + + + + + +
    +
    + +
    +

    Intro to Python frameworks & Django

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + + +
    +

    Class outline:

    + +
      +
    • Review +
    • About Python frameworks +
    • About Django +
    • Django MVT +
    • Getting started with Django +
    +
    +
    +

    Review: HTTP requests & JSON

    +
    +
    +

    What is HTTP?

    +

    Hypertext Transfer Protocol (HTTP) is how we send data and files around the Web

    +

    HTTP works as a request-response protocol between a client and server.

    +
      +
    • Client could be a web browser (operated by a human) or an application (like a computer running a Python program)
    • +
    • Server could be a computer with files (like HTML) stored on it, or an application serving up data through an API
    • +
    +
    +
    +

    HTTP requests

    +

    An HTTP request consists of:

    +
      +
    1. Method (required) GET, PUT, POST, etc
    2. +
    3. Request URI (required) Full URI, including any query parameters
    4. +
    5. Header(s) (optional) Ex: API token)
    6. +
    7. Body (optional) Ex: data you want to send
    8. +
    +
    
    +                        curl # Command-line tool used to send HTTP requests
    +                        -X GET # Method
    +                        -H 'Accept: application/json' # Header
    +                        # Request URI
    +                        'https://api.open-meteo.com/v1/forecast?latitude=43.07&longitude=-89.40&hourly=temperature_2m'
    +                    
    +
    +
    +

    HTTP requests

    +

    Common request methods

    + + + + + + + +
    GETRetreive data from a specified resource
    POSTSend data to a server (usually via an API) to create/overwrite a resource
    PUTSend data to a server (usually via an API) to create/update a resource
    DELETEDelete a specified resource
    +
    +
    +

    Requests module

    +

    The Requests module is a third-party library, + and is the de-facto standard for sending HTTP requests and receiving responses using Python.

    +

    On your own machine, you need to install requests before you can import it into Python files

    +
    
    +                        pip install requests
    +                    
    +

    Requests module documentation

    +
    +
    +

    Requests module

    +

    In Replit, install requests by clicking Tools > Packages, then searching for "requests"

    + +
    +
    +

    Making a GET request

    +

    requests.get() sends an HTTP request and returns an HTTP response object

    +
    
    +                        import requests
    +                        response = requests.get("https://girldevelopit.com")
    +                        print(vars(response))
    +                    
    +
    +
    +

    What's in a Response?

    +

    Lots of stuff! See full list. The values we're typically concerned about are: + + + + + + +
    .status_codeStatus code of the request (200 OK, 404 Not found, etc)
    .text, .json or .rawBody of the response (stored in different attributes, depending on the type of response
    .headersHTTP response headers, with details about the response content and where it came from
    +

    +
    +

    What's in a Response?

    +

    Let's look at some response values

    +
    
    +                            import requests
    +
    +                            response = requests.get("https://girldevelopit.com")
    +                            print(response.status_code) # HTTP status code (200)
    +                            print(response.headers) # Content-type tells us what kind of response this is (text/html)
    +                            print(response.text) # The full body of the response (HTML, in this case)
    +                        
    +
    +
    +

    What's an API?

    +

    An Application Programming Interface (API) is a way for 2 separate computer systems to communicate. Essentially, it's a set of rules for retrieving, creating, updating and/or deleting data in another system.

    +

    There are many different types of APIs, but on the Web we're typically talking about RESTful APIs, which allow 2 applications to exchange data securely over the Internet. RESTful APIs use URIs to identify resources.

    +
    +
    +

    The NASA APOD API

    +

    NASA posts an Astronomy Picture of the Day each day, which is also available via an API. To use this API, you first need to register for a key at https://api.nasa.gov

    + +
    +
    +

    The NASA APOD API

    +

    After registering, you should recieve a key, along with a sample request.

    + +
    +
    +

    Query parameters

    +

    In the NASA API, your key is added as a query paramter

    +
    
    +                        ?api_key=eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn&start_date=2023-01-01
    +                    
    +

    Query parameters ("params") are key/value pairs that allow adding extra context to a URL.

    +
      +
    • Query param portion of a URL begins with ?
    • +
    • Each additional param is preceded with &
    • +
    +
    
    +                        https://api.nasa.gov/planetary/apod?api_key=eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn&start_date=2023-01-01
    +                    
    +

    Params are specific to seach site/app/API - there's no universal set of available params

    +
    +
    +

    The NASA APOD API

    +

    Let's run this in Python

    +
    
    +                        import requests
    +
    +                        # per NASA API docs, we need to pass the key as a query parameter
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
    +                        print(response.status_code)
    +                        print(response.headers)
    +                    
    +
    +
    +

    About JSON

    +

    Javascript Object Notation (JSON) is an open standard file format that stores data in key/value pairs. It looks a lot like a Python dictionary!

    +

    Requests has a built-in .json() method for parsing JSON responses, and Python has a built-in JSON library, too.

    +
    
    +                        import requests
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
    +                        print(response.json())
    +                    
    +
    +
    +

    JSON example

    + +
    
    +                        {
    +                            'copyright': 'Mike Selby',
    +                            'date': '2023-02-04',
    +                            'explanation': 'Centered in this colorful cosmic canvas, NGC 2626 is a beautiful, bright, blue reflection nebula in the southern Milky Way. Next to an obscuring dust cloud and surrounded by reddish hydrogen emission from large H II region RCW 27 it lies within a complex of dusty molecular clouds known as the Vela Molecular Ridge. NGC 2626 is itself a cloud of interstellar dust reflecting blue light from the young hot embedded star visible within the nebula. But astronomical explorations reveal many other young stars and associated nebulae in the star-forming region. NGC 2626 is about 3,200 light-years away. At that distance this telescopic field of view would span about 30 light-years along the Vela Molecular Ridge.',
    +                            'hdurl': 'https://apod.nasa.gov/apod/image/2302/NGC_2626_CDK_700_II_20_Jan_2023.jpg',
    +                            'media_type': 'image',
    +                            'service_version': 'v1',
    +                            'title': 'NGC 2626 along the Vela Molecular Ridge',
    +                            'url': 'https://apod.nasa.gov/apod/image/2302/NGC_2626_CDK_700_II_20_Jan_2023_1024.jpg'
    +                        }
    +                    
    +
    +
    +

    Accessing JSON values

    +

    Once the response values are parsed as JSON, we can treat it like a dictionary and access individual fields with bracket notation.

    +
    
    +                        import requests
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +                        response = requests.get("https://api.nasa.gov/planetary/apod", params=params)
    +                        json = response.json()
    +                        url = json['url']
    +                        print(url)
    +                    
    +
    +
    +

    HTTP status exceptions

    +

    Requests includes custom exception types, such as HTTP error, which covers issues like 404 not found and 403 access denied (bad credentials).

    +

    Requests does not automatically raise HTTP exceptions; we need to do that explicitly with the .raise_for_status() method and handle the exception.

    +
    +
    +

    Handling HTTP errors

    +
    
    +                        import requests
    +
    +                        params = {'api_key': 'eIkpQYXKa6mq1J75qPMYc0Rvit3K8wNaytEJCnTn'}
    +
    +                        try:
    +                            response = requests.get("https://api.nasa.gov/planetary/apo", params=params)
    +                            response.raise_for_status()
    +                            json = response.json()
    +                            url = json['url']
    +                            print(url)
    +                        except requests.exceptions.HTTPError as e:
    +                            print("Oh no, an error happened: ", e)
    +                    
    +
    +
    +

    Exercise review: Requests

    +

    Class10Ex1Requests

    +
    +
    +

    Python frameworks

    +
    +
    +

    What's a framework?

    +

    Software frameworks are packages of starter code that you can build on. They're often used to develop web applications quickly. Frameworks do things like:

    +
      +
    • Provide code for common pieces of functionality, like serving web pages and authenticating users
    • +
    • Help you follow security best practices without having to be a web security expert
    • +
    • Allow you to focus on building functionality that's unique to your app
    • +
    +
    +
    +

    How is a framework different from a package/module?

    +
      +
    • Modules that we import into Python (ex, Requests) are smaller bundles of code that serve a very specific purpose. They are building blocks that help us create larger apps.
    • +
    • Frameworks are larger packages of code which include all the basic parts needed for a full web application. We can still add modules as needed to extend a framework!
    • +
    +
    +
    +

    Python web app frameworks

    +

    There are many Python frameworks out there! The 2 most popular general-purpose frameworks for web applications are:

    + +

    Both allow you to build web applications and/or APIs, and both have a robust extension ecosystem

    +
    +
    +

    Django

    +
    +
    +

    Django features

    +

    In this class, we'll use Django. Its features include:

    +
      +
    • Built-in web server for development and testing
    • +
    • Functionality for processing HTTP requests with custom logic
    • +
    • Template system for displaying dynamic web pages to users
    • +
    • Database connectivity + built-in methods for reading/writing
    • +
    • Data modeling functionality to support converting between database data and Python objects
    • +
    • Built-in admin interface + authentication features
    • +
    • And much more! See feature overview
    • +
    +
    +
    +

    Ways to use Django

    +
      +
    • All-in-one MVT (model-view-template) app, which means that both the app logic and the HTML page construction happen on the server side, within Django. This doesn't allow page content to change after loading, unless you add Javascript over the top.
    • +
    • REST API backend only that performs app logic and returns JSON to a separate frontend app (ex, a Javascript framework like React or Angular). This is a more "modern" approach that allows content to change after page load.
    • +
    +

    In this class, we'll use the MVT approach

    +
    +
    +

    Django MVT

    +
    +
    +

    Django MVT

    +
      +
    • Model The data access layer. This layer contains everything about the data: how to access it, how to validate it, which behaviors it has, and the relationships between the data. Note that this layer is not required! Sometimes a request only generates a view, which populates a template.
    • +
    • View The logic layer. This layer contains the logic that accesses the model and populates the appropriate template.
    • +
    • Template The presentation layer. This layer defines how something should be displayed on a Web page .
    • +
    +
    +
    +

    Django MVT

    + +
    +
    +

    Getting started with Django

    +
    +
    +

    Installing Django locally

    + +
    +
    +

    Django in Replit

    +

    For our project, we'll run Django in Replit. From here on out, we'll follow this tutorial:

    +

    Python 2 Django tutorial

    +

    The tutorial will guide us through building a simple Django web app the displays the current weather based on the user's location.

    +
    +
    +

    Homework!

    +

    For next time, please make sure you've completed tutorial steps 1-3!

    +

    Also, please register for an OpenWeather API key! (step 1 in Configure OpenWeather API key)

    +
    + + +
    +
    + Ex1 + + + + + + + diff --git a/deloitte-python-2-jan-2023/class11/django-tutorial.md b/deloitte-python-2-jan-2023/class11/django-tutorial.md new file mode 100644 index 0000000..59dba7e --- /dev/null +++ b/deloitte-python-2-jan-2023/class11/django-tutorial.md @@ -0,0 +1,432 @@ +# Tutorial: Build a web app with Django & Replit + +In this tutorial, we'll create a basic Django app in Replit that displays the weather for the user's location, based on their IP address. See a completed version of this in Replit at [https://replit.com/@lizkrznarich/Python2WeatherAppFinished](https://replit.com/@lizkrznarich/Python2WeatherAppFinished) + +1. [Django project setup](#django-project-setup) +2. [Create homepage templates](#create-homepage-templates) +3. [Create homepage view & configure URL](#create-homepage-view--configure-url) +4. [Get the user's IP address](#get-the-users-ip-address) +5. [Get the user's location](#get-the-users-location) +6. [Configure OpenWeather API key](#configure-openweather-api-key) +7. [Get the current weather for the user's location](#get-weather-data-for-the-users-location) +8. [Add CSS stylesheets](#add-css-stylesheets) +9. [Add a chart with Plotly](#add-a-chart-with-plotly) +10. [Bonus activity: Add weather icons](#bonus-activity-add-weather-icons) + +# Django project setup + +Before we can get started, we first need to set up a new Django project in Replit. + +1. Sign into your Replit account at [replit.com](https://replit.com). If you don't have an account, create a new one. + +2. In Replit, click the **+ Create** button. In the window that opens, type **django** in the Template field and choose the **django replit** option from the dropdown. Optionally, add a custom title in the Title field and click **+ Create Repl** + +![](../images/create-repl-django.png) + +3. The basic Django file structure will appear in the **Files** panel at left. Click **README.MD** to see the instructions for getting Django up and running. + +4. Per **README.MD**, open the **Shell** tab in the right panel and run the following command to generate a secret key. + + python + import secrets + secrets.token_urlsafe(32) + +![](../images/django-gen-key.png) + +5. Copy the generated key, then click the **Secrets** icon in the **Tools** section of the left panel. In the **Secrets** tab that opens in the right panel, type **SECRET_KEY** in the **key** field, paste the generated key in the **value** field, and **Click Add new secret**. + +![](../images/dajngo-save-key.png) + +6. Click the green **Run** button. Once Django has started, a page with the message "The install worked successfully! Congratulations!" should appear in the **Webview** tab at right. This is your Django app! Click Open in new tab to view it in full screen. + +![](../images/django-success.png) + + +# Create homepage templates + +In this section, we'll add HTML templates for our homepage and configure Django to look for our templates in the correct directory. Django includes its own [template system](https://docs.djangoproject.com/en/4.1/topics/templates). Components of the template system include: + +- [Variables](https://docs.djangoproject.com/en/4.1/topics/templates/#variables) allow passing data from our Python code into templates. Data is passed in a dictionary, and template variables enclosed in ```{{ }}``` +- [Tags](https://docs.djangoproject.com/en/4.1/topics/templates/#tags) allow adding various bits of logic to your templates. Django includes a large [library of built-in tags](https://docs.djangoproject.com/en/4.1/ref/templates/builtins/#ref-templates-builtins-tags). Tags are enclosed in ```{% %}``` + + +1. In the **Files** panel, hover over **django_project**, click the 3 dots icon and choose **Add folder**. + +![](../images/django-add-folder.png) + +2. Type **templates** in the folder name box and press **Enter/Return** to create the folder. + +3. Hover over **templates**, click the 3 dots icon and choose **Add file**. + +![](../images/django-add-file.png) + +4. Type **base.html** in the file name box and press**Enter/Return** to create the file. + +5. Copy the template code below and paste it into the **base.html** file. This will be the parent template for all of our other templates. + + + + + + + Hello World! + + + + + {% block content %}{% endblock content %} + + + +6. Create another file inside **templates** named **index.html**. Copy the code below and paste it into the **index.html** file. The line between ```{% block content %}``` and ```{% endblock content %}``` will be inserted where ```{% block content %}{% endblock content %}``` is located in the parent base.html template. + + {% extends "base.html" %} + + {% block content %} +

    Hello World!

    + {% endblock content %} + +7. We need to tell Django where to look for our template files. In the **Files** panel, click **settings.py** to open it. Scroll to the **TEMPLATES** section and replace the line that begins with **DIR** with the code below. + + 'DIRS': [os.path.join(BASE_DIR, 'django_project', 'templates')], + +![](../images/django-settings-dirs.png) + +# Create homepage view & configure URL + +In this section, we'll create a new view that points to the homepage template, and then configure a URL to point to the view. + +7. Create a new file inside **django_project** named **views.py** and paste the code below to create a new view that directs to our index.html template. + + from django.shortcuts import render + + def index(request): + return render(request, 'index.html') + +8. Finally, we need to link our view to a URL. In the Files panel, click the **django_project** folder, then click **urls.py**. In the imports section add the line below. + + from . import views.py + +9. Add the following line to the url_patterns list to configure a new URL pattern that points to our index view. + + path('', views.index, name='index'), + +10. The complete urls.py should look like this: + + from django.contrib import admin + from django.urls import path + from . import views + + urlpatterns = [ + path('', views.index, name='index'), + path('admin/', admin.site.urls), + ] + +11. Open the **Webview** tab (Tools > Webview). You should see a "Hello world!" message from your index template. + +![](../images/django-hello-world.png) + +# Get the user's IP address + +In order to get the user's location, we first need to get their IP address. An IP address identifies the device that a user's request is coming from. + +1. Open **views.py** and update the **index(request)** function so that it gets the user's IP address from the built-in Django request object and passes it to the index.html template. The user's IP address can be located either in the ```HTTP_X_FORWARDED_FOR``` or ```REMOTE_ADDR``` request header, depending on their network configuration, so we need to check both headers. + + def index(request): + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + if x_forwarded_for: + ip = x_forwarded_for.split(',')[0] + else: + ip = request.META.get('REMOTE_ADDR') + return render(request, 'index.html', {'ip': ip}) + +2. Open the **index.html** template and add the line below Hello World. + +

    You are visiting from IP address {{ ip }}

    + +3. Your page should now show the IP address you are visting from! + +![](../images/django-ip.png) + +# Get the user's location + +Now that we have the user's IP, we can get the geolocation information associated with that IP. We'll use [https://ip-api.com](https://ip-api.com) and the requests module for this. IP API is very simple - send a request in format http://ip-api.com/json/24.177.113.128, and it will return a JSON response with the corresponding location data: + + {"status":"success","country":"United States","countryCode":"US","region":"WI","regionName":"Wisconsin","city":"Madison","zip":"53705","lat":43.0725,"lon":-89.4491,"timezone":"America/Chicago","isp":"Charter Communications","org":"Spectrum","as":"AS20115 Charter Communications","query":"24.177.113.128"} + +1. Open **views.py** and add the requests module to the list of imports. + + import requests + +2. Add a new function to views.py that sends a requests to ip-api.com + + def get_location_from_ip(ip_address): + response = requests.get("http://ip-api.com/json/" + ip_address) + return response.json() + +3. Call the new function from your **index(request)** function and assign the response to a variable, and pass that data to the template. + + def index(request): + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + if x_forwarded_for: + ip = x_forwarded_for.split(',')[0] + else: + ip = request.META.get('REMOTE_ADDR') + location = get_location_from_ip(ip) + return render(request, 'index.html', {'ip': ip, 'location': location}) + +4. Add the user's location info to the **index.html** template by pasting the following line beneath "You are visiting from...". + +

    You are located in {{ location }}

    + +![](../images/django-location-json.png) + +5. Oops! The raw response from ip-api.com doesn't look so nice. We can get individual values using the syntax below. + +

    You are located in {{ location.city }}, {{ location.region }}, {{ location.country_Code }}

    + +![](../images/django-location-pretty.png) + + +# Configure OpenWeather API key + +We'll get weather data from [OpenWeather](https://openweathermap.org) using their [Current Weather API](https://openweathermap.org/current). To use this API, we first need to register for a key and configure that key in our Django settings file. + +1. Register for an OpenWeather API key at [https://home.openweathermap.org/users/sign_up](https://home.openweathermap.org/users/sign_up). You do NOT need to tick the checkboxes to receive emails from OpenWeather. + +![](../images/django-open-weather.png) + +2. Visit the **API Keys** tab in your account and copy the value in the **Key** field. Note! It can take up to 2 hours for a new key to become active. + +![](../images/django-open-weather-key.png) + +3. In Replit, click the **Secrets** icon in the **Tools** section of the left panel. In the **Secrets** tab that opens in the right panel, type **OPEN_WEATHER_KEY** in the **key** field, paste your OpenWeather API key in the **value** field, and **Click Add new secret**. + +![](../images/django-replit-open-weather-secret.png) + +4. In the **Files** panel, click **settings.py** to open it. At the bottom of the file, add a new line with the code below. + + OPEN_WEATHER_KEY = os.getenv('OPEN_WEATHER_KEY') + +![](../images/django-settings-open-weather-token.png) + +*Note: We could paste this key directly into our code, but that presents a security risk. If our code becomes public (either on purpose or accidentally), others could use our key maliciously. Keys should be treated like passwords, they should never be placed directly in code.* + +# Get weather data for the user's location + +Now that we have the user's location and our OpenWeather API key, we can get the current weather for that location using a request in the format ```https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}&units=imperial```. + +1. Open **views.py** and import the settings file. This is how we share values between files in Python! + + from . import settings + +3. Open **views.py** and add a new function that sends a requests to api.openweathermap.org + + def get_weather_from_location(location): + token = os.environ.get("OPEN_WEATHER_TOKEN") + url = "https://api.openweathermap.org/data/2.5/weather?lat=" + location['lat'] + "&lon=" + location['lat'] + "&units=imperial&appid=" + settings.OPEN_WEATHER_KEY + response = requests.get(url) + return response.json() + +*Note: the url above is a very long string. We can use Pythons built-in string method [.format()](https://docs.python.org/3/library/stdtypes.html#str.format) to shorten it a bit. In place of each ```{}``` in the string, Python will substitute an argument passed to .formt(), in order from left to right.* + + url = "https://api.openweathermap.org/data/2.5/weather?lat={}&lon={}&units=imperial&appid={}".format(location['lat'], location['lon'], settings.OPEN_WEATHER_KEY) + +4. Call the new function from your **index(request)** function and assign the response to a variable, and pass that data to the template. + + def index(request): + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + if x_forwarded_for: + ip = x_forwarded_for.split(',')[0] + else: + ip = request.META.get('REMOTE_ADDR') + location = get_location_from_ip(ip) + weather = get_weather_from_location(location) + return render(request, 'index.html', {'ip': ip, 'location': location, 'weather': weather}) + +5. Add the weather info for the user's location to the **index.html** template by pasting the following line beneath "You are located in...". + +

    Current weather: {{ weather }}

    + +![](../images/django-weather-json.png) + +6. Like with location, ```weather``` contains the entire OpenWeather JSON response. We can make things prettier by displaying just specific values. Update the "Current weather" line in **index.html** with the code below. + +

    Current weather:

    + + + + +
    Temperature{{ weather.main.temp }} F
    Wind{{ weather.wind.speed }} mph
    Conditions{{ weather.weather.0.description }}
    + +![](../images/django-weather-pretty.png) + +# Add CSS stylesheets + +Our app works great, but it doesn't look so good. We'll add some basic styles using the [Twitter Bootstrap framework](https://getbootstrap.com/), then customize it with a local CSS stylesheet. + +1. Add the Twitter Bootstrap CSS file to your templates by pasting the code below into **base.html**, inside the `````` tags. + + + +2. We won't cover Bootstrap in depth here, but we can borrow some formatting from the [Bootstrap example file](https://github.com/twbs/examples/blob/main/starter/index.html#L48). Update your **index.html** file to add the div tags below. + + {% extends "base.html" %} + + {% block content %} +
    +
    +

    Current weather

    +

    You are visiting from IP address {{ ip }}

    +

    You are located in {{ location.city }}, {{ location.region }}, {{ location.countryCode }}

    +
    + + + + +
    Temperature{{ weather.main.temp }} F
    Wind{{ weather.wind.speed }} mph
    Conditions{{ weather.weather.0.description }}
    +
    +
    + {% endblock content %} + +![](../images/django-weather-bootstrap.png) + +3. That's looking better already, but we can customize it further by adding our own CSS file. First, we need a folder to hold our static web assets, like CSS and images. In the **Files** panel, hover over **django_project**, click the 3 dots icon and choose **Add folder**. + +4. Type **static** in the folder name box and press **Enter/Return** to create the folder. Important! Django is pre-configured to look for static assets in a folder named "static". + +5. Create a new folder named **css** inside the **static** folder that you just created. + +6. Hover over **css**, click the 3 dots icon and choose **Add file**. + +7. Type **style.css** in the file name box and press**Enter/Return** to create the file. + +8. Paste the code below into the **style.css** file. + + body { + background-color: lightblue; + } + + h1 { + color: navy; + } + + .container { + background-color: white; + border-radius: .5em; + padding: 1em; + width: 50%; + margin-right: auto; + margin-left: auto; + } + +9. Django knows that static assets should be in a folder named **static**, but we still need to tell Django where to look for the **static** folder. Open **settings.py**, look for the line with ```STATIC_URL = '/static/'``` and paste the code below on the next line. + + STATICFILES_DIRS = (os.path.join(BASE_DIR, 'django_project', 'static'), ) + +![](../images/django-weather-static-settings.png) + +10. Finally, we need to add our CSS file to our templates. Open **base.html** and paste ``{% load static %}``` at the top of the file. Paste the code below inside ``````, on the line after the Boostrap CSS that we just added. + + + +![](../images/django-weather-custom-css.png) + +# Add a chart with Plotly + +[Plotly](https://plotly.com) developes a "low code" framework called [DASH](https://dash.plotly.com/) that allows easily building graphs/charts and complete dashboards to visualize data. DASH, in turn, uses the Python Flask web app framework. + +Plotly also makes its underlying code open source and publishes Python packages that allow you to create same types of charts/graphs in Python applications that don't use the full DASH framework. + +There are several different ways to build data visualizations using [Plotly Python libraries](https://pypi.org/project/plotly). In this section, we'll use the [Plotly Graph Objects](https://plotly.com/python/graph-objects/) library to create a very simple bar chart using the temperature data returned by the OpenWeather API. + +We're only touching the very tip of the Plotly iceberg here! For (much) more information, see [Plotly docs](https://plotly.com/pytho). Tutorials point also has a nice [tutorial about creating charts with Graph Objects](https://www.tutorialspoint.com/plotly/plotly_bar_and_pie_chart.htm). + +1. To use Plotly, we first need to install it in our Replit environment. In the right sidebar, click **Packages**, search for Plotly in the window that opens, and click the **+** to install it. + +![](../images/replit-install-plotly.png) + +2. To make Django aware of our newly-installed package, we need to restart it. To restart, click the **Stop** button at the top of the screen, then click the **Run** button. + +3. In your **views.py** file, add the following import statements beneath the existing imports. + + import plotly.graph_objs as go + import plotly.io as pio + +4. In **views.py**, add a new function that creates a bar chart with some hard-coded data by copying and pasting the code below. This functions returns the entire bar chart will be returned as HTML, which we can pass to our template. + + def get_chart(): + temp_types = ['High', 'Low', 'Feels like'] + temps = [35, 17, 23] + data = [go.Bar(x=temp_types, y=temps)] + fig = go.Figure(data=data) + return pio.to_html(fig) + +We use the [.Bar() method](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Bar.html) of the plotly.graph_objects library to create a new bar chart data object and the [.Figure() method](https://plotly.com/python-api-reference/generated/plotly.graph_objects.Figure.html) to create the rendered figure. Finally, we use the [.to_html()](https://plotly.com/python-api-reference/generated/plotly.io.to_html.html) method of the plotly.io library to convert the rendered chart to HTML. These methods accept many more arguments that allow for customization - read the docs for details! + +5. Update your **index()** function to call the **get_chart()** function and pass the returned chart to the template. + + def index(request): + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + if x_forwarded_for: + ip = x_forwarded_for.split(',')[0] + else: + ip = request.META.get('REMOTE_ADDR') + location = get_location_from_ip(ip) + weather = get_weather_from_location(location) + chart = get_chart() + + return render(request, 'index.html', { + 'ip': ip, + 'location': location, + 'weather': weather, + 'chart': chart + }) + +6. In **index.html**, add the lines below beneath the closing `````` tag to display the chart. By default, Django templates interpret string variables as text (not code). To parse the value of the ```chart``` variable as raw HTML markup, we need to add ```{% autoescape off %}{% endautoescape %}``` template tags ([autoescape docs](https://docs.djangoproject.com/en/4.1/ref/templates/builtins/#autoescape)). + +
    + {% autoescape off %} + {{ chart }} + {% endautoescape %} + +7. After refreshing your **Webview**, you should see a chart appear + +![](../images/django-chart.png) + +8. Let's update our **get_chart()** function to use dynamic data from the OpenWeather API. In **views.py**, we have an existing variable ```weather``` that contains the OpenWeather API response. Update your code to pass ```weather``` to ```get_chart()```. + + ... + def get_chart(weather): + ... + chart = get_chart(weather) + ... + +9. In your **get_chart()** function, replace **temps** with the code below. + + temps = [ + weather['main']['temp_max'], + weather['main']['temp_min'], + weather['main']['feels_like'] + ] + +10. After refreshing your **Webview**, you should see the chart updated with the dynamic values. + +![](../images/django-chart-dynamic.png) + +# Bonus activity: Add weather icons + +Each OpenWeather API response includes a code for an icon that represents the current weather condition. You can get the image that corresponds to each code from OpenWeather and add display it in your application, along with the weather data. See the [Weather Icons documentation](https://openweathermap.org/weather-conditions) + +Try adding the corresponding weather icon to your Django app! + +![](../images/django-icon.png) + + + + + + + + + diff --git a/deloitte-python-2-jan-2023/class12/class12.html b/deloitte-python-2-jan-2023/class12/class12.html new file mode 100644 index 0000000..fb80933 --- /dev/null +++ b/deloitte-python-2-jan-2023/class12/class12.html @@ -0,0 +1,306 @@ + + + + + + Django project + + + + + + + + +
    +
    + +
    +

    Django project

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + + +
    +

    Class outline:

    + +
      +
    • Review +
    • Getting external data in Django +
    • Django template variables +
    • Charts with Plotly +
    • Wrap-up +
    +
    +
    +

    Review: Frameworks

    +
    +
    +

    What's a framework?

    +

    Software frameworks are packages of starter code that you can build on. They're often used to develop web applications quickly. Frameworks do things like:

    +
      +
    • Provide code for common pieces of functionality, like serving web pages and authenticating users
    • +
    • Help you follow security best practices without having to be a web security expert
    • +
    • Allow you to focus on building functionality that's unique to your app
    • +
    +
    +
    +

    Python web app frameworks

    +

    There are many Python frameworks out there! The 2 most popular general-purpose frameworks for web applications are:

    + +

    Both allow you to build web applications and/or APIs, and both have a robust extension ecosystem

    +
    +
    +

    Django features

    +

    In this class, we'll use Django. Its features include:

    +
      +
    • Built-in web server for development and testing
    • +
    • Functionality for processing HTTP requests with custom logic
    • +
    • Template system for displaying dynamic web pages to users
    • +
    • Database connectivity + built-in methods for reading/writing
    • +
    • Data modeling functionality to support converting between database data and Python objects
    • +
    • Built-in admin interface + authentication features
    • +
    • And much more! See feature overview
    • +
    +
    +
    +

    Ways to use Django

    +
      +
    • All-in-one MVT (model-view-template) app, which means that both the app logic and the HTML page construction happen on the server side, within Django. This doesn't allow page content to change after loading, unless you add Javascript over the top.
    • +
    • REST API backend only that performs app logic and returns JSON to a separate frontend app (ex, a Javascript framework like React or Angular). This is a more "modern" approach that allows content to change after page load.
    • +
    +

    In this class, we'll use the MVT approach

    +
    +
    +

    Django MVT

    +
      +
    • Model The data access layer. This layer contains everything about the data: how to access it, how to validate it, which behaviors it has, and the relationships between the data. Note that this layer is not required! Sometimes a request only generates a view, which populates a template.
    • +
    • View The logic layer. This layer contains the logic that accesses the model and populates the appropriate template.
    • +
    • Template The presentation layer. This layer defines how something should be displayed on a Web page .
    • +
    +
    +
    +

    Django MVT

    + +
    +
    +

    Installing Django locally

    + +
    +
    +

    Django in Replit

    +

    For our project, we'll run Django in Replit. From here on out, we'll follow this tutorial:

    +

    Python 2 Django tutorial

    +

    The tutorial will guide us through building a simple Django web app the displays the current weather based on the user's location.

    +
    +
    +

    Homework review

    + +
    +
    +

    Wrap-up

    +
    +
    +

    We learned so much!

    +
      +
    • Reading/writing files +
    • Working with files & folders +
    • Argument parsing +
    • Error handling +
    • HTTP requests & APIs +
    • Python frameworkds +
    +
    +
    +

    What's next?! πŸŽ‰ 🐍

    +
    +
    +

    Learning opps

    + +
    +
    +

    Next topics to explore

    +
      +
    • Custom classes (Object-oriented programming) +
    • Decorators/higher order functions +
    • Containerizing & deploying Python apps +
    • Testing +
    +
    +
    +

    But really, you need to practice coding!

    +

    Hands-on project ideas:

    + +
    +
    +

    Thank you & happy coding!

    +
    +
    +
    + Ex1 + + + + + + + diff --git a/deloitte-python-2-jan-2023/class7/class7.html b/deloitte-python-2-jan-2023/class7/class7.html new file mode 100644 index 0000000..6884e60 --- /dev/null +++ b/deloitte-python-2-jan-2023/class7/class7.html @@ -0,0 +1,794 @@ + + + + + + Welcome to Python 2! + + + + + + + + +
    +
    + +
    +

    Welcome to Python 2!

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    +
    +

    Welcome!

    +

    Girl Develop It is here to provide affordable and accessible programs to learn software through mentorship and hands-on instruction.

    + +

    Classroom "rules":

    +
      +
    • I am here for you!
    • +
    • Every question is important
    • +
    • Help each other
    • +
    • Have fun
    • +
    +
    +
    +

    Class series outline

    + +

    This may change if we end up needing more or less time for certain topics.

    +
      +
    • Class 7: Review & reading from/writing to files +
    • Class 8: More file operations, argument parsing & list comprehension +
    • Class 9: Error handling +
    • Class 10: HTTP requests +
    • Class 11: Intro to Python frameworks & object-oriented Python +
    • Class 12: Your own app with Django! (get data from an external API and create a visualization) +
    +

    (note: Python 1 series included classes 1-6)

    +
    +
    +

    Class logistics

    + +
    +
    +

    Introductions

    +

    Tell us about yourself:

    +
      +
    • Name +
    • Preferred pronouns +
    • Location +
    • Programming experience & did you participate in the Python 1 class series? +
    • What do you hope to learn in this class series? +
    +
    +
    +

    Today's topics:

    + +
      +
    • Repl.it coding environment +
    • Quick review of Python 1 topics +
    • Reading from/writing to files +
    • Review final Python 1 exercise +
    +
    +
    +

    Repl.it setup

    +
    +
    +

    Coding Python in Repl.it

    + +

    Installing/running Python on lots of different systems/versions is tricky.

    +

    In this class, we'll use Replit, an online editor.

    + +

    + https://replit.com +

    +
    +
    +

    Repl.it setup

    +
      +
    • Create a Replit account +
    • Once you're logged in, create a new Python Repl +
    + screenshot of repl +
    +
    +

    Using Replit

    +

    Type code in the left panel (main.py file) & click "Run". Output is shown in the right panel (console).

    +

    You can also type code directly in the console panel (press Enter key to run).

    + screenshot of repl +
    +
    +

    Review from Python 1

    +
    + +
    +

    Data types & structures

    +
    +
    +

    Simple data types

    + + + + + + + + +
    Data type + Example values +
    Integers + 2 44 -3 +
    Floats + 3.14 4.5 -2.0 +
    Booleans + True False +
    Strings + 'Β‘hola!' 'its python time!' +
    +
    +
    + Name bound to value +

    Variables

    + +

    A name can be bound to a value. +

    +

    A name that's bound to a data value is also known as a variable.

    +
    +

    One way to bind a name is with an assignment statement:

    + + + + +
    x + = + 7 +
    Name + + Value +
    +
    +

    The value can be any expression:

    + + + + +
    x + = + 1 + 2 * 3 - 4 // 5 +
    Name + + Expression +
    +
    +
    +
    +

    Naming conventions for variables & functions

    +
      +
    • Use a lowercase single letter (variables only), word, or words +
    • Separate words with underscores +
    • Make names meaningful, ex first_name rather than fn +
    +

    +

    Examples

    +
      +
    • m (variables only) +
    • hobby +
    • my_fav_hobby +
    +
    +
    +

    Data structures

    + +

    A data structure is a particular way of organizing data in a computer so that it can be used effectively.

    +
    +

    Data structures in programming are a bit like lists and tables in text docs/presentations - we use them to organize information and make it more meaningful/useful.

    + + +
    +
    +

    Lists

    +

    A list is a container that holds a sequence of related pieces of information.

    +

    Lists can hold any Python values, separated by commas:

    +
    
    +                    # all strings
    +                    members = ["Liz", "Tinu", "Brenda", "Kaya"]
    +                    # all integers
    +                    ages_of_kids = [1, 2, 7]
    +                    # all floats
    +                    prices = [79.99, 49.99, 89.99]
    +                    # mixed types
    +                    mixed_types = ["Liz", 7, 79.99]
    +                    
    +
    +
    +

    Tuples

    + +

    A tuple is like a list, but immutable: its values cannot be changed after the initialization.

    +

    Tuples are enclosed in parentheses (9.99, 7.99, 3.99)

    + +
    
    +                    position = (100, 50)
    +                    prices = (9.99, 7.99, 3.99)
    +                    
    +
    +
    +

    Dictionaries

    +

    A dict is a mutable mapping of key-value pairs

    +
    
    +					states = {
    +						"CA": "California",
    +						"DE": "Delaware",
    +						"NY": "New York",
    +						"TX": "Texas",
    +						"WY": "Wyoming"
    +					}
    +					
    +

    Dictionaries allow you to access values using a human-readable name ("key") rather than an index number. Dictionaries map very well to JSON!

    +
    +
    +

    Functions & methods

    +
    +
    +

    Built-in functions

    + +

    Python has lots of built-in functions. Built-in functions are not specific to a particular data type - they often work on multiple data types (but check the docs!)
    + Some examples are:

    + +
    
    +                    pow(2, 100)
    +                    
    + +
    
    +                    max(50, 300)
    +                    
    + +
    
    +                    min(-1, -300)
    +                    
    +
    +
    +

    Importing functions & modules

    + +

    Some functions from the Python standard library are available by default. + Others are included with a basic Python installation, but need to be imported + into your current file before they can be used.

    + +

    Import a single function from the Operator module :

    + +
    +
    
    +                    from operator import add
    +
    +                    18 + 69
    +                    add(18, 69)
    +                    
    +
    +
    +
    +

    Built-in methods

    + +

    Each data type has a set of built-in methods that only work on that data type. Check the Python data types docs to see which methods are available for a given data type.
    + Examples of string methods are:

    + + + + + + + + + + + +
    Function + Description +
    .upper() + Returns a copy of the string with all characters converted to uppercase +
    .lower() + Returns a copy of the string with all characters converted to lowercase +
    .title() + Returns a titlecased version of the string where words start with an uppercase character and the remaining characters are lowercase +
    .swapcase() + Returns a copy of the string with uppercase characters converted to lowercase and vice versa +
    .strip() + Returns a copy of the string with the leading and trailing whitespace characters removed +
    + +
    + +
    +

    Defining functions

    + +

    We define functions in Python with a def statement.

    + +
    
    +                    def <name>(<parameters>):
    +                        return <return expression>
    +                    
    + +

    Example:

    +
    
    +                        def add(num1, num2):             # ← Function signature
    +                            sum = num1 + num2            # ← Function body
    +                            return sum                   # ← Function body
    +                        
    +

    Once defined, we can call it:

    +
    
    +                    add(2, 2)
    +                    add(18, 69)
    +                    
    +
    +
    +

    Conditionals

    +
    +
    +

    Conditional statements

    + +

    A conditional statement gives you a way to execute + a different set of code statements based on whether certain + conditions are true or false.

    + +
    
    +                    if <condition>:
    +                        <statement>
    +                        <statement>
    +                        ...
    +                    
    + +

    A simple conditional:

    + +
    
    +                    clothing = "shirt"
    +
    +                    if temperature < 32:
    +                        clothing = "jacket"
    +                    
    +
    +
    +

    Comparison operators

    + + + + + + + +
    Operator Meaning True expressions +
    == Equality 32 == 32 +
    != Inequality 30 != 32 +
    > Greater than 60 >= 32 +
    >=Greater than or equal 60 >= 32 , 32 >= 32 +
    < Less than 20 < 32 +
    <= Less than or equal 20 < 32, 32 <= 32 +
    +
    +

    ⚠️ Common mistake: Do not confuse = (the assignment operator) with == (the equality operator).

    +
    +
    +

    Logical operators

    + + + + + +
    OperatorTrue expressions Meaning +
    and 4 > 0 and -2 < 0 Evaluates to True if both cconditions are true; otherwise evaluates to False. +
    or 4 > 0 or -2 > 0 Evaluates to True if either condition is true; evaluates to False only if both are false. +
    not not (5 == 0) Evaluates to True if condition is false; evaluates to False if condition is true. +
    +

    W3Schools has a handy Python operators reference

    +
    +
    +

    if/elif/else statements summary

    + +
    
    +                        def get_number_sign(num):
    +                            if num < 0:
    +                                sign = "negative"
    +                            elif num > 0:
    +                                sign = "positive"
    +                            else:
    +                                sign = "neutral"
    +                            return sign
    +                    
    + +

    Syntax tips:

    +
      +
    • Always start with if clause. +
    • Zero or more elif clauses. +
    • Zero or one else clause, always at the end. +
    +
    +
    +

    Loops

    +
    +
    +

    While loops

    + +

    The while loop syntax:

    + +
    
    +                    while <condition>:
    +                        <statement>
    +                        <statement>
    +                    
    + +

    As long as the condition is true, the statements below it are executed.

    + +
    
    +                    multiplier = 1
    +                    while multiplier <= 5:
    +                        print(9 * multiplier)
    +                        multiplier += 1
    +                    
    +
    +
    +

    For loop

    +

    The other type of loop supported in Python is a for loop

    +

    The for loop syntax:

    + +
    
    +                    for <value> in <sequence>:
    +                        <statement>
    +                        <statement>
    +                    
    + +

    For loops provide a clean way of repeating code for each item in a data structure (like a list).

    +
    +
    +

    Looping through a list

    +

    😍 For loops love lists!

    +
    
    +                    scores = [80, 95, 78, 92]
    +                    total = 0
    +                    for score in scores:
    +                        total += score
    +                    
    +
    +

    This does the same thing as a while loop with a counter, but with less code.

    +
    
    +                    scores = [80, 95, 78, 92]
    +                    total = 0
    +                    i = 0
    +                    while i < len(scores):
    +                        score = scores[i]
    +                        total += score
    +                        i += 1
    +                    
    +
    +
    +
    +

    Loops in functions

    + +

    A loop in a function will commonly use a parameter to determine some aspect of its repetition.

    + +
    
    +                    def sum_up_squares(start, end):
    +                        counter = start
    +                        total = 0
    +                        while counter <= end:
    +                          total += pow(counter, 2)
    +                          counter += 1
    +                        return total
    +
    +                    sum_up_squares(1, 5)
    +                    
    +
    +
    +

    Loops in functions

    +
    
    +                    def calculate_average(scores):
    +                        total = 0
    +                        for score in scores:
    +                            total += score
    +                        return total / len(scores)
    +
    +                    scores = [80, 95, 78, 92]
    +                    average_score = calculate_average(scores)
    +                    
    +
    +
    +

    Python 1 materials

    + +

    Find all the slides & exercises from Python 1 at
    + https://lizkrznarich.github.io/gdi-python-1 +

    +
    +
    +

    Working with files

    +
    +
    +

    CSV files

    +

    Comma Separated Value (CSV) is a plain text format used to store "tabular" data (aka rows and columns), like from a spreadsheet or database table.

    +

    Because CSV is simple and non-proprietary, it's commonly used to exchange data between different applications.

    +
    
    +                        Brittany, 9.15, 9.4, 9.3, 9.2
    +                        Lea, 9, 8.8, 9.1, 9.5
    +                        Maya, 9.2, 8.7, 9.2, 8.8
    +                    
    + +
    +
    +

    Opening files

    +

    We use the Python built in open() method to open files for reading or writing.

    +

    The keyword with tells Python to automatically close the file when we're finished.

    +
    
    +                        with open('filename') as my_file:
    +                            # do something
    +                    
    +

    See the docs on python.org for more

    +
    +
    +

    Reading files with CSV module

    +

    Python has a built-in CSV module that includes many features used for reading/writing CSV files.

    + Open a CSV and read its contents (docs at python.org) +
    
    +                        # import the csv module
    +                        import csv
    +                        # open the file
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            # load the contents of the CSV file into a variable
    +                            csv_reader = csv.reader(my_file)
    +                            # CSV is a nested list!
    +                            # now we can loop through the rows in the file
    +                            for row in csv_reader:
    +                                print(row)
    +                    
    +
    +
    +

    Reading files with CSV module

    +

    A CSV is a list of rows, which are lists of values.

    +

    We can use nested for loops to get values from rows and cells.

    +
    
    +                        import csv
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            csv_reader = csv.reader(my_file, delimiter=',')
    +                            for row in csv_reader:
    +                                print(row)
    +                                for cell in row:
    +                                    print(cell)
    +                    
    +
    +
    +

    Exercise review: Reading from a CSV file

    +

    A simple grade calculator

    + +
    +
    +

    Forking Replit files

    +
      +
    1. Click the link to the Replit, ex https://replit.com/@lizkrznarich/Class6Ex2CsvDataHeaders +
    2. Click Fork Repl
      + +
    3. Click Edit in workspace + +
    +
    +
    +

    Writing CSV files

    +
    +
    +

    Writing files with CSV module

    +

    The CSV module also has support for writing files (docs) +

    
    +                        import csv
    +                        my_list = [
    +                                ["Mon", "Oatmeal", "Salad", "Pasta"],
    +                                ["Tues", "Waffles", "Soup", "Tacos"],
    +                                ["Wed", "Cereal", "Sandwich", "Pizza"]
    +                            ]
    +                        # open a new or existing file for writing
    +                        with open('fun_spreadsheet.csv', 'w') as my_file:
    +                            # prepare the CSV for writing
    +                            writer = csv.writer(my_file)
    +                            # write data from a list to the CSV file
    +                            writer.writerows(my_list)
    +                    
    +
    +
    +

    CSV files with headers

    +
    +
    +

    Reading CSV files with headers

    +

    Use csv.DictReader to read a CSV file with headers

    +
    
    +                        # import the csv module
    +                        import csv
    +                        # open the file
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            # load the contents of the CSV file into a variable
    +                            csv_reader = csv.DictReader(my_file)
    +                            # CSV read as dict with column headers as keys!
    +                            # now we can loop through the rows in the file
    +                            # and get the values from specific columns
    +                            for row in csv_reader:
    +                                print(row)
    +                    
    +
    +
    +

    Exercise review: CSV with headers

    +

    Let's re-visit our gradebook exercise...

    + +
    +
    +

    Exercise: Multiple files

    +

    Get bits of data from multiple files and put it together into a nicely formatted report.

    + +
    +
    +

    Feedback survey

    +

    Please fill out the GDI feedback survey + to help us improve future classes. Thanks!

    +
    +
    +
    + + + + + + + + + diff --git a/deloitte-python-2-jan-2023/class8/class8.html b/deloitte-python-2-jan-2023/class8/class8.html new file mode 100644 index 0000000..cc13797 --- /dev/null +++ b/deloitte-python-2-jan-2023/class8/class8.html @@ -0,0 +1,541 @@ + + + + + + Files, OS and argparse + + + + + + + + +
    +
    + +
    +

    More file operations & argument parsing

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    +
    +

    Class outline:

    + +
      +
    • Review +
    • Working with different types of files +
    • Working with directories (the OS module) +
    • Passing & parsing arguments +
    +
    +
    +

    Review: CSV

    +
    +
    +

    Opening files for reading/writing

    + +

    open(file, mode='r', ...): + Returns a file object for the specified file and mode. +

    +

    The keyword with tells Python to automatically close the file when we're finished.

    +
    
    +                    with open("myinfo", "r") as my_file:
    +                        # do something
    +                    
    +
    +
    +

    open() modes

    +

    A few of the possible modes:

    + + + + + + + +
    Character + Mode + Description +
    r + Read + Default mode used if a mode isn't specified. If the file does not exist, this raises an error. +
    w + Write + If the file does not exist, this mode creates it. + If file already exists, this mode deletes all data + and writes new data from the beginning of the file. +
    a + Append + If the file does not exist, this mode creates it. + If file already exists, this mode appends data to end + of existing data. +
    +
    +
    +

    Writing files with CSV module

    +

    The CSV module has support for writing files (docs)

    +

    A CSV is essentially a list of lists, with each list representing a row in the CSV.

    +
    
    +                        import csv
    +                        my_list = [
    +                                ["Day", "Breakfast", "Lunch", "Dinner"],
    +                                ["Mon", "Oatmeal", "Salad", "Pasta"],
    +                                ["Tues", "Waffles", "Soup", "Tacos"],
    +                                ["Wed", "Cereal", "Sandwich", "Pizza"]
    +                            ]
    +                        # open a new or existing file for writing
    +                        with open('fun_spreadsheet.csv', 'w') as my_file:
    +                            # prepare the CSV for writing
    +                            writer = csv.writer(my_file)
    +                            # write data from a list to the CSV file
    +                            writer.writerows(my_list)
    +                    
    +
    +
    +

    Reading files with CSV module

    +

    We can also read files with the CSV module, using nested for loops to get values from rows and cells.

    +
    
    +                        import csv
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            csv_reader = csv.reader(my_file, delimiter=',')
    +                            for row in csv_reader:
    +                                print(row)
    +                                for cell in row:
    +                                    print(cell)
    +                    
    +
    +
    +

    Reading CSV files with headers

    +

    Use csv.DictReader to read a CSV file with headers

    +
    
    +                        # import the csv module
    +                        import csv
    +                        # open the file
    +                        with open('fun_spreadsheet.csv') as my_file:
    +                            # load the contents of the CSV file into a variable
    +                            csv_reader = csv.DictReader(my_file)
    +                            # CSV is a dict with column headers as keys!
    +                            # now we can loop through the rows in the file
    +                            # and get the values from specific columns
    +                            for row in csv_reader:
    +                                print(row)
    +                    
    +
    +
    +

    Exercise review

    + +
    +
    +

    More on files

    +
    +
    +

    Types of files

    + + + + + + +
    Type + Description +
    Text + Contains one or more lines that contain text characters, + encoded according to a character encoding (like UTF-8 or ASCII). + Each file ends with a control character:
    +
      +
    • Unix/Linux: Line feed (\n) +
    • Mac: Carriage return (\r) +
    • Windows: Both (\n\r) +
    +

    +
    Binary + Any file that is not a text file. The bytes are typically + intended to be interpreted as something other than a text file, + according to the file extension.
    + e.g. images (GIF/JPG/PNG/), audio files (WAV/MP3), video files (MOV/MP4), + compressed files (ZIP/RAR). +
    +
    +
    +

    File formats

    +

    The Python standard library has support for parsing:

    +
      +
    • Plain text (.txt) +
    • CSV (.csv) +
    • JSON (.json) +
    • HTML (.html) +
    • HTML (.xml) +
    +

    It also supports zip and tar archives

    +

    Many 3rd party modules are available in PyPi!
    + pdf, docx, Google docs, markdown, etc

    +
    +
    +

    Writing to text files

    +

    Use the built-in file.write() method to write to a text file:

    +

    Write items in a list to a new file:

    +
    
    +                    authors = ["Ursula K. Le Guin", "N. K. Jemisin", "Octavia E. Butler"]
    +                    with open("authors.txt", "w") as file:
    +                        for author in authors:
    +                            file.write(author + "\n")
    +                    
    +

    Note that we have to add a line ending to each item - Python doesn't add it automatically

    +
    +
    +

    Writing to text files

    +

    Add lines to an existing file:

    +
    
    +                    more_authors = ["Toni Morrison", "Zora Neale Hurston"]
    +                    with open("authors.txt", "a") as file:
    +                        for author in more_authors:
    +                            file.write(author + "\n")
    +                    
    +
    +
    +

    Reading a whole text file

    +

    Use the built-in read() method to + receive the entire contents of the file as a string.

    +
    
    +                    with open("authors.txt", "r") as file:
    +                        authors = file.read()
    +                        print(authors)
    +                    
    +
    +
    +

    Reading a text file line by line

    +

    Use the readlines() method to + receive the entire file as a list of strings (one for each line).

    +
    
    +                    with open("authors.txt", "r") as file:
    +                        authors = file.readlines()
    +                        print(authors)
    +                    
    +
    +
    +

    Working with directories
    (the OS module)

    +
    +
    +

    What happens if we try to write to a file in a directory (folder) that doesn't exist?

    +
    
    +                    authors = ["Ursula K. Le Guin", "N. K. Jemisin", "Octavia E. Butler"]
    +                    with open("data/authors.txt", "a") as file:
    +                        for author in authors:
    +                            file.write(author + "\n")
    +
    +                    FileNotFoundError: [Errno 2] No such file or directory: 'data/authors.txt'
    +                    
    +
    +
    +

    OS module

    +

    The OS module is part if the standard Python library + and contains loads of functions for interacting with a + computer's operating system, including: +

      +
    • Creating directories +
    • Renaming/deleting files & folders +
    • Listing files in a directory +
    • Setting file permissions +
    • Getting and setting environment variables +
    • Managing processes +
    +

    +
    +
    +

    Create directories

    +

    Create a directory using os.makdir()

    +
    
    +                        import os
    +                        os.mkdir('./data')
    +                        # now we can create a new file inside our dir
    +                        authors = ["Ursula K. Le Guin", "N. K. Jemisin", "Octavia E. Butler"]
    +                        with open("data/authors.txt", "a") as file:
    +                            for author in authors:
    +                                file.write(author + "\n")
    +                    
    +
    +
    +

    List files in a directory

    +

    Check what's inside a directory using os.listdir().
    + This function returns a list of filenames as strings.

    +
    
    +                        import os
    +                        files = os.listdir('./data')
    +                        for file in file:
    +                            print(file)
    +                    
    +
    +
    +

    OS.path module

    +

    The os.path module is also part if the standard Python library + and contains handy functions for getting information about files, including: +

      +
    • Checking if a file/directory exists +
    • Checking if a thing is a file or a directory +
    • Extracting parts of a filepath, such as the parent directory, the filename or the fiel extension +
    +

    +
    +
    +

    Check if a file/directory exists

    +

    If we try to create a directory that already exists, we get an error.
    + It's a good practice to check whether a directory exists before creating a new one using os.path.exists()

    +

    os.path.exists() returns True or False

    +
    
    +                        import os
    +                        if not os.path.exists('./data'):
    +                            os.mkdir('./data')
    +                    
    +
    +
    +

    Get the file extension

    +

    Sometimes you need to get just file names or extensions. + Use os.path.splitext() to return a list with 2 items: the file name and the extension

    +
    
    +                        import os
    +                        files = os.listdir('./data')
    +                        for file in file:
    +                            split = os.path.splitext(file)
    +                            name = split[0]
    +                            print(name)
    +                            extension  = split[1]
    +                            print(extension)
    +                    
    +
    +
    +

    Passing command-line arguments

    +
    +
    +

    What are arguments?

    +

    We often need to pass bits of data into a script, so that the script can serve + different use cases without needing to edit the code in the script.
    + Ex, we may want to run a script that processes files on different directories. +

    +

    To do this, we use command-line arguments that we can customize for a given script.

    +
    
    +                        python main.py -d my_dir
    +                    
    +
    +
    +

    argparse module

    +

    The argparse module is part of the standard Python library + and contains functions that allow accepting and processing command line arguments, + as well as providing help text to users. +

    +
    +
    +

    Definining arguments

    +

    add_argument() is used to define a new argument.
    + A name is required, and additional parameters can also be set, such as:

    +
      +
    • type automatically convert an argument to the given type (str, int, float, etc). Default is str. +
    • required whether an argument is required or optional (True or False). Default is False. +
    • help message for the script user about the argument +
    • choices limit values to a specific set of choices (formatted as a list or range, ex ['foo', 'bar']) +
    +
    +
    +

    Definining arguments

    +
    
    +                        import argparse
    +                        # initialize the argument parser
    +                        parser=argparse.ArgumentParser()
    +                        # define an argument
    +                        parser.add_argument('-d', '--directory',
    +                                            type=str,
    +                                            required=True,
    +                                            help='The directory that report files are located in')
    +                    
    +

    Note: 1 argument can have multiple names. It's common to support both a short -d and long --directory name version. + - and -- before short and long names are not required, but they are common convention in CLI commands.

    +
    +
    +

    Using argument values

    +

    parse_args() is used to extract values passed in as arguments +

    
    +                        import argparse
    +                        # initialize the argument parser
    +                        parser=argparse.ArgumentParser()
    +                        # define an argument
    +                        parser.add_argument('-d', '--directory',
    +                                            type=str,
    +                                            required=True,
    +                                            help='The directory that report files are located in')
    +                        # parse the arguments
    +                        args=parser.parse_args()
    +                        # get a specifc argument value
    +                        directory = args.directory
    +                    
    +
    +
    +

    Passing arguments in Replit

    +

    The Replit Run button does the equivalent of typing python main.py into a command line interface (CLI).

    +

    We can access the CLI in Replit by switching the right panel from Console to Shell

    +
    +
    +

    Passing arguments in Replit

    + screenshot showing replit shell +
    +
    +

    Exercise

    +

    Let's update our quarterly report exercise to get the monthly report files automatically.

    + +
    +
    +
    + + + + + + + + + diff --git a/deloitte-python-2-jan-2023/class9/class9.html b/deloitte-python-2-jan-2023/class9/class9.html new file mode 100644 index 0000000..640fe7d --- /dev/null +++ b/deloitte-python-2-jan-2023/class9/class9.html @@ -0,0 +1,808 @@ + + + + + + Errors + + + + + + + + +
    +
    + +
    +

    Error handling

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    + + +
    +

    Class outline:

    + +
      +
    • Review +
    • Syntax errors & linting +
    • Logic errors & testing +
    • Runtime errors & exception handling +
    +
    +
    +

    Review: OS and argparse

    +
    +
    +

    OS module

    +

    The OS module is part if the standard Python library + and contains loads of functions for interacting with a + computer's operating system, including: +

      +
    • Creating directories +
    • Renaming/deleting files & folders +
    • Listing files in a directory +
    • Setting file permissions +
    • Getting and setting environment variables +
    • Managing processes +
    +

    +
    +
    +

    Create directories

    +

    Create a directory using os.makdir()

    +
    
    +                        import os
    +                        os.mkdir('./data')
    +                        # now we can create a new file inside our dir
    +                        authors = ["Ursula K. Le Guin", "N. K. Jemisin", "Octavia E. Butler"]
    +                        with open("data/authors.txt", "a") as file:
    +                            for author in authors:
    +                                file.write(author + "\n")
    +                    
    +
    +
    +

    List files in a directory

    +

    Check what's inside a directory using os.listdir().
    + This function returns a list of filenames as strings.

    +
    
    +                        import os
    +                        files = os.listdir('./data')
    +                        for file in file:
    +                            print(file)
    +                    
    +
    +
    +

    OS.path module

    +

    The os.path module is also part if the standard Python library + and contains handy functions for getting information about files, including: +

      +
    • Checking if a file/directory exists +
    • Checking if a thing is a file or a directory +
    • Extracting parts of a filepath, such as the parent directory, the filename or the fiel extension +
    +

    +
    +
    +

    Check if a file/directory exists

    +

    If we try to create a directory that already exists, we get an error.
    + It's a good practice to check whether a directory exists before creating a new one using os.path.exists()

    +

    os.path.exists() returns True or False

    +
    
    +                        import os
    +                        if not os.path.exists('./data'):
    +                            os.mkdir('./data')
    +                    
    +
    +
    +

    Get the file extension

    +

    Sometimes you need to get just file names or extensions. + Use os.path.splitext() to return a list with 2 items: the file name and the extension

    +
    
    +                        import os
    +                        files = os.listdir('./data')
    +                        for file in file:
    +                            split = os.path.splitext(file)
    +                            name = split[0]
    +                            print(name)
    +                            extension  = split[1]
    +                            print(extension)
    +                    
    +
    +
    +

    argparse module

    +

    The argparse module is part of the standard Python library + and contains functions that allow accepting and processing command line arguments, + as well as providing help text to users. +

    +
    +
    +

    Defining arguments

    +

    add_argument() is used to define a new argument.
    + A name is required, and additional parameters can also be set, such as:

    +
      +
    • type automatically convert an argument to the given type (str, int, float, etc). Default is str. +
    • required whether an argument is required or optional (True or False). Default is False. +
    • help message for the script user about the argument +
    • choices limit values to a specific set of choices (formatted as a list or range, ex ['foo', 'bar']) +
    +
    +
    +

    Defining arguments

    +
    
    +                        import argparse
    +                        # initialize the argument parser
    +                        parser=argparse.ArgumentParser()
    +                        # define an argument
    +                        parser.add_argument('-d', '--directory',
    +                                            type=str,
    +                                            required=True,
    +                                            help='The directory that report files are located in')
    +                    
    +

    Note: 1 argument can have multiple names. It's common to support both a short -d and long --directory name version. + - and -- before short and long names are not required, but they are common convention in CLI commands.

    +
    +
    +

    Using argument values

    +

    parse_args() is used to extract values passed in as arguments +

    
    +                        import argparse
    +                        # initialize the argument parser
    +                        parser=argparse.ArgumentParser()
    +                        # define an argument
    +                        parser.add_argument('-d', '--directory',
    +                                            type=str,
    +                                            required=True,
    +                                            help='The directory that report files are located in')
    +                        # parse the arguments
    +                        args=parser.parse_args()
    +                        # get a specifc argument value
    +                        directory = args.directory
    +                    
    +
    +
    +

    Multiple arguments

    +

    Can we have multiple arguments? Of course! +

    
    +                        import argparse
    +                        # initialize the argument parser
    +                        parser=argparse.ArgumentParser()
    +                        # define an argument
    +                        parser.add_argument('-d', '--directory',
    +                                            type=str,
    +                                            required=True,
    +                                            help='The directory that report files are located in')
    +                        parser.add_argument('-n', '--name',
    +                                            type=str,
    +                                            required=True,
    +                                            help='Your name')
    +                        # parse the arguments (parse_args() parses all arguments)
    +                        args=parser.parse_args()
    +                        # get a specifc argument value
    +                        directory = args.directory
    +                        name = args.name
    +                    
    +
    +
    +

    Passing arguments in Replit

    +

    The Replit Run button does the equivalent of typing python main.py into a command line interface (CLI).

    +

    We can access the CLI in Replit by switching the right panel from Console to Shell

    +
    +
    +

    Passing arguments in Replit

    + screenshot showing replit shell +
    +
    +

    Exercise review

    + +
    +
    +

    Errors

    +
    +
    +

    Types of errors

    + +

    These are common to all programming languages:

    +
      +
    • Syntax errors
    • +
    • Logic errors
    • +
    • Runtime errors
    • +
    +
    +
    +

    Syntax errors

    +
    +
    +

    Syntax errors

    +

    Each programming language has syntactic rules. + If the rules aren't followed, the program cannot be parsed + and will not be executed at all.

    + +

    Spot the syntax errors:

    +
    
    +                    if x > 5 # Missing colon
    +                       x += 1
    +                    
    +
    
    +                    sum = 0
    +                    for x in range(0, 10):
    +                       sum + = x # No space needed between + and =
    +                    
    +
    
    +                        def my_func(num_1, num_2):
    +                           sum = num_1 + num_2
    +                        return sum # Return is not indented
    +                        
    + +
    + +
    +

    Common syntax errors

    +
      +
    • Extra or missing parenthesis +
    • Missing colon at the end of an if, while, def statements, etc. +
    • Missing/unmatched quotes +
    • Incorrect/misaligned indents +
    +

    + +

    To fix a syntax error, read the message carefully and go through your code with a critical eye. πŸ‘
    + ...and lint your code!

    + +
    + +
    +

    Linting

    + +

    To avoid syntax errors, use a linting tool to check your code as you write it. Many IDEs have a Python linter built in or available as an extension (ex: VSCode Python linting).

    + +

    You can also run Pylint on your code

    + +
    
    +                    # import pylint
    +                    # Already installed in Replit - no import needed
    +                    def sum(a, b):
    +                        total = a + b
    +                    return total
    +                    
    +

    In Replit, switch to the Shell tab and type pylint main.py and press Enter.
    + When prompted to select a version, press Enter again.

    +
    +
    +

    Exercise

    +

    Fix this code!

    +

    Class9Ex1SyntaxErrors

    +
    +
    +

    Logic errors

    +
    +
    +

    Logic errors

    + +

    A program has a logic error if it does not behave as expected. + Typically discovered via failing tests or bug reports from users. +

    + +

    Spot the logic error:

    +
    
    +                    # Which medal goes to the first place winner?
    +                    medals = ["gold", "silver", "bronze"]
    +                    first_place = medals[1]
    +                    print(first_place)
    +                    
    +

    To avoid the wrath of angry users due to logic errors, write tests!

    +
    +
    +

    Testing

    + +

    There are several Python testing frameworks. Pytest is a good one to start with.

    + +
    
    +                    import pytest
    +
    +                    medals = ["gold", "silver", "bronze"]
    +                    def get_medal(place):
    +                        return medals[place]
    +
    +                    def test_get_medal():
    +                        assert get_medal(1) == "gold"
    +                    
    +

    In Replit, click Run to install Pytest, then switch to the Shell tab and type pytest main.py and press Enter.

    +
    +
    +

    Exercise: Pytest

    +

    Add a test with Pytest

    +

    Class9Ex2Pytest

    +
    +
    +

    Runtime errors

    +
    + +
    +

    Runtime errors

    +

    Even with testing and linting, errors can slip through!

    +

    A runtime error happens while a program is running, + often halting the execution of the program. +

    + +

    Spot the runtime error:

    +
    
    +                    def div_numbers(dividend, divisor):
    +                        return dividend/divisor
    +
    +                    quot1 = div_numbers(10, 2)
    +                    quot2 = div_numbers(10, 1)
    +                    quot3 = div_numbers(10, 0)  # Cannot divide by 0!
    +                    quot4 = div_numbers(10, -1)
    +                    
    + +

    To prevent runtime errors, code defensively and write tests for all edge cases.

    +
    + +
    +

    NameError

    + +

    What it technically means: +
    + Python looked up a name but couldn't find it +

    + +

    What it practically means: +

      +
    • You made a typo +
    +

    + +

    What you should look for: +

      +
    • A typo in the name +
    +

    + +

    Example:

    + +
    
    +                    fav_nut = 'pistachio'
    +                    best_chip = 'chocolate'
    +                    trail_mix = Fav_Nut + best__chip
    +                    
    + +
    +
    +

    ...NoneType...

    + +

    What it technically means: +
    + You used None (null) in some operation it wasn't meant for +

    + +

    What it practically means: +
    + You forgot a return statement in a function +

    + +

    What you should look for: +

      +
    • Functions missing return statements +
    • Printing instead of returning a value +
    +

    + +

    Example:

    + +
    
    +                    def sum(a, b):
    +                        print(a + b)
    +
    +                    total = sum( sum(30, 45), sum(10, 15) )
    +                    
    + +
    + +
    +

    TypeError:'X' object is not callable

    + +

    What it technically means: +
    + Objects of type X cannot be treated as functions +

    + +

    What it practically means: +
    + You accidentally called a non-function as if it were a function +

    + +

    What you should look for: +

      +
    • Parentheses after variables that aren't functions +
    • Variables with same name as a function +
    +

    + +

    Example:

    + +
    
    +                    sum = 2 + 2
    +                    sum(3, 5)
    +                    
    +
    +
    +

    TraceBacks

    +
    + +
    +

    What's a traceback?

    + +

    When there's a runtime error in your code, + you'll see a traceback in the console.

    + +
    
    +                        def div_numbers(dividend, divisor):
    +                            return dividend/divisor
    +
    +                        quot1 = div_numbers(10, 2)
    +                        quot2 = div_numbers(10, 1)
    +                        quot3 = div_numbers(10, 0)
    +                        quot4 = div_numbers(10, -1)
    +                    
    + +
    
    +                    Traceback (most recent call last):
    +                        File "main.py", line 14, in <module>
    +                            quot3 = div_numbers(10, 0)
    +                        File "main.py", line 10, in div_numbers
    +                            return dividend/divisor
    +                    ZeroDivisionError: division by zero
    +                    
    +
    + +
    +

    Parts of a Traceback

    + +
      +
    • The error message itself +
    • Lines #s on the way to the error +
    • What’s on those lines +
    + +

    The most recent line of code is always last (right before the error message).

    + +
    
    +                    Traceback (most recent call last):
    +                        File "main.py", line 14, in <module>
    +                            quot3 = div_numbers(10, 0)
    +                        File "main.py", line 10, in div_numbers
    +                            return dividend/divisor
    +                    ZeroDivisionError: division by zero
    +                    
    +
    + + +
    +

    Reading a Traceback

    + +
      +
    1. Read the error message (remember what common error messages mean!) +
    2. Look at each line, bottom to top, + and see if you can find the error. +
    + +
    
    +                    Traceback (most recent call last):
    +                        File "main.py", line 14, in <module>
    +                            quot3 = div_numbers(10, 0)
    +                        File "main.py", line 10, in div_numbers
    +                            return dividend/divisor
    +                    ZeroDivisionError: division by zero
    +                    
    +
    +
    +

    Exceptions

    +
    + +
    +

    Exceptions

    + +

    Python raises an exception whenever a runtime error occurs. + An exception is a mechanism in many languages used to declare and respond to "exceptional" conditions.

    + +

    How an exception is reported:

    +
    
    +                    >>> 10/0
    +                    Traceback (most recent call last):
    +                        File "<stdin>", line 1, in 
    +                    ZeroDivisionError: division by zero
    +                    
    + +

    If an exception is not handled, the program stops executing immediately.

    +
    +
    +

    The try statement

    + +

    To handle an exception (keep the program running), use a try statement.

    + +
    
    +                    try:
    +                        <code you want to run if all goes well>
    +                    except:
    +                        <code you want to run if this particular exception happens>
    +                       ...
    +                    
    + +

    The <try statement> is executed first. + If and exception is raised with the <try statement> executes, + the <except statement> is executed. +

    +
    +
    +

    Try statement example

    + +
    
    +                    try:
    +                        quot = 10/0
    +                    except:
    +                        print("An error happened")
    +                        quot = 0
    +                    
    +
    + +
    +

    Getting error details

    +

    To get the error message that Python returned, we need to catch the Exception and assign it to a variable.

    +
    
    +                    try:
    +                        quot = 10/0
    +                    except Exception as e:
    +                        print('Handling an error:', e)
    +                        quot = 0
    +                    
    +
    +
    +

    Default Exception

    +

    All exception types are derived from the parent class Exception.

    +
      +
    • Exception can be used as a wildcard that catches (almost) everything
    • +
    • It can be used on its own, or as a last resort to catch exceptions that you haven't caught with a more specific type
    • +
    +
    +
    +

    Types of exceptions

    + +

    A few exception types and examples of buggy code:

    + + + + + + + + +
    Exception + Example +
    TypeError + 'hello'[1] = 'j' +
    IndexError + 'hello'[7] +
    NameError + x += 5 +
    FileNotFoundError + open('dsfdfd.txt') +
    + +

    See full list in the exceptions docs. Note: Third party Python packages often include their own custom exception types!

    + +
    +
    +

    Catching a specific exception type

    +

    In some cases, we need to catch and handle specific exceptions. Multiple except statements that catch different exception types are allowed. It's a best practice to catch the default Exception, in addition to specific types.

    +
    
    +                    try:
    +                        quot = 10/0
    +                    except ZeroDivisionError as e:
    +                        print('Handling zero division exception:', e)
    +                        quot = 0
    +                    except Exception as e:
    +                        print('Something else went wrong:', e)
    +                    
    +
    +
    +

    Try inside a function

    +
    
    +                    def div_numbers(dividend, divisor):
    +                        try:
    +                            quotient = dividend/divisor
    +                        except ZeroDivisionError as e:
    +                            print('Handling zero division exception:', e)
    +                            quotient = 0
    +                        except Exception as e:
    +                            print('Something else went wrong:', e)
    +                            quotient = None
    +                        return quotient
    +
    +                    div_numbers(10, 2)
    +                    div_numbers(10, 0)
    +                    div_numbers(10, 'foo')
    +                    
    +

    Depending on the case, we may want to place the return statement inside the try statement, so that there is only a return value if the code succeeds.

    +
    +
    +

    System Exit

    +

    To stop the program if a certain exception is encountered, move the return statement inside the try statement and raise a SystemExit() inside the except statement. +

    
    +                    def div_numbers(dividend, divisor):
    +                        try:
    +                            quotient = dividend/divisor
    +                        except ZeroDivisionError as e:
    +                            print('Encountered error:', e)
    +                            quotient = 0
    +                        except Exception as e:
    +                            print('Something else went wrong:', e)
    +                            raise SystemExit()
    +                        return quotient
    +
    +                    div_numbers(10, 2)
    +                    div_numbers(10, 0)
    +                    div_numbers(10, -1)
    +                    
    +
    +
    +

    Exercise: Try/Except

    + +

    Let's make our report code a bit more robust with some error handling

    + +

    Class9Ex3TryExcept

    +
    +
    +
    + + + + + + + + + diff --git a/deloitte-python-2-jan-2023/images/advanced-search.png b/deloitte-python-2-jan-2023/images/advanced-search.png new file mode 100644 index 0000000..cd3ca64 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/advanced-search.png differ diff --git a/deloitte-python-2-jan-2023/images/call_expression_anatomy.png b/deloitte-python-2-jan-2023/images/call_expression_anatomy.png new file mode 100644 index 0000000..38b8155 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/call_expression_anatomy.png differ diff --git a/deloitte-python-2-jan-2023/images/console_application.png b/deloitte-python-2-jan-2023/images/console_application.png new file mode 100644 index 0000000..16b2149 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/console_application.png differ diff --git a/deloitte-python-2-jan-2023/images/create-repl-django.png b/deloitte-python-2-jan-2023/images/create-repl-django.png new file mode 100644 index 0000000..a723228 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/create-repl-django.png differ diff --git a/deloitte-python-2-jan-2023/images/create-repl.png b/deloitte-python-2-jan-2023/images/create-repl.png new file mode 100644 index 0000000..069dce8 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/create-repl.png differ diff --git a/deloitte-python-2-jan-2023/images/dajngo-save-key.png b/deloitte-python-2-jan-2023/images/dajngo-save-key.png new file mode 100644 index 0000000..3816ade Binary files /dev/null and b/deloitte-python-2-jan-2023/images/dajngo-save-key.png differ diff --git a/deloitte-python-2-jan-2023/images/desktop_application.png b/deloitte-python-2-jan-2023/images/desktop_application.png new file mode 100644 index 0000000..b0a6a00 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/desktop_application.png differ diff --git a/deloitte-python-2-jan-2023/images/django-add-file.png b/deloitte-python-2-jan-2023/images/django-add-file.png new file mode 100644 index 0000000..6fec5c5 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-add-file.png differ diff --git a/deloitte-python-2-jan-2023/images/django-add-folder.png b/deloitte-python-2-jan-2023/images/django-add-folder.png new file mode 100644 index 0000000..94b5869 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-add-folder.png differ diff --git a/deloitte-python-2-jan-2023/images/django-chart-dynamic.png b/deloitte-python-2-jan-2023/images/django-chart-dynamic.png new file mode 100644 index 0000000..ca1c53c Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-chart-dynamic.png differ diff --git a/deloitte-python-2-jan-2023/images/django-chart.png b/deloitte-python-2-jan-2023/images/django-chart.png new file mode 100644 index 0000000..df954e5 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-chart.png differ diff --git a/deloitte-python-2-jan-2023/images/django-gen-key.png b/deloitte-python-2-jan-2023/images/django-gen-key.png new file mode 100644 index 0000000..bddbae1 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-gen-key.png differ diff --git a/deloitte-python-2-jan-2023/images/django-hello-world.png b/deloitte-python-2-jan-2023/images/django-hello-world.png new file mode 100644 index 0000000..049f3e5 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-hello-world.png differ diff --git a/deloitte-python-2-jan-2023/images/django-icon.png b/deloitte-python-2-jan-2023/images/django-icon.png new file mode 100644 index 0000000..5e54dbc Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-icon.png differ diff --git a/deloitte-python-2-jan-2023/images/django-ip.png b/deloitte-python-2-jan-2023/images/django-ip.png new file mode 100644 index 0000000..34e2970 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-ip.png differ diff --git a/deloitte-python-2-jan-2023/images/django-location-json.png b/deloitte-python-2-jan-2023/images/django-location-json.png new file mode 100644 index 0000000..c5629ef Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-location-json.png differ diff --git a/deloitte-python-2-jan-2023/images/django-location-pretty.png b/deloitte-python-2-jan-2023/images/django-location-pretty.png new file mode 100644 index 0000000..54e1628 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-location-pretty.png differ diff --git a/deloitte-python-2-jan-2023/images/django-new-app.png b/deloitte-python-2-jan-2023/images/django-new-app.png new file mode 100644 index 0000000..129570b Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-new-app.png differ diff --git a/deloitte-python-2-jan-2023/images/django-open-weather-key.png b/deloitte-python-2-jan-2023/images/django-open-weather-key.png new file mode 100644 index 0000000..05c8c1b Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-open-weather-key.png differ diff --git a/deloitte-python-2-jan-2023/images/django-open-weather.png b/deloitte-python-2-jan-2023/images/django-open-weather.png new file mode 100644 index 0000000..f695713 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-open-weather.png differ diff --git a/deloitte-python-2-jan-2023/images/django-replit-open-weather-secret.png b/deloitte-python-2-jan-2023/images/django-replit-open-weather-secret.png new file mode 100644 index 0000000..3f87fae Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-replit-open-weather-secret.png differ diff --git a/deloitte-python-2-jan-2023/images/django-settings-dirs.png b/deloitte-python-2-jan-2023/images/django-settings-dirs.png new file mode 100644 index 0000000..fa7417e Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-settings-dirs.png differ diff --git a/deloitte-python-2-jan-2023/images/django-settings-open-weather-token.png b/deloitte-python-2-jan-2023/images/django-settings-open-weather-token.png new file mode 100644 index 0000000..ab511f0 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-settings-open-weather-token.png differ diff --git a/deloitte-python-2-jan-2023/images/django-success.png b/deloitte-python-2-jan-2023/images/django-success.png new file mode 100644 index 0000000..25cbfb6 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-success.png differ diff --git a/deloitte-python-2-jan-2023/images/django-weather-bootstrap.png b/deloitte-python-2-jan-2023/images/django-weather-bootstrap.png new file mode 100644 index 0000000..5ab2cd5 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-weather-bootstrap.png differ diff --git a/deloitte-python-2-jan-2023/images/django-weather-custom-css.png b/deloitte-python-2-jan-2023/images/django-weather-custom-css.png new file mode 100644 index 0000000..b7eff1f Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-weather-custom-css.png differ diff --git a/deloitte-python-2-jan-2023/images/django-weather-json.png b/deloitte-python-2-jan-2023/images/django-weather-json.png new file mode 100644 index 0000000..4a26d75 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-weather-json.png differ diff --git a/deloitte-python-2-jan-2023/images/django-weather-pretty.png b/deloitte-python-2-jan-2023/images/django-weather-pretty.png new file mode 100644 index 0000000..3442ac6 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-weather-pretty.png differ diff --git a/deloitte-python-2-jan-2023/images/django-weather-static-settings.png b/deloitte-python-2-jan-2023/images/django-weather-static-settings.png new file mode 100644 index 0000000..5bf2c62 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django-weather-static-settings.png differ diff --git a/deloitte-python-2-jan-2023/images/django.png b/deloitte-python-2-jan-2023/images/django.png new file mode 100644 index 0000000..bc88492 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django.png differ diff --git a/deloitte-python-2-jan-2023/images/django_mvt.png b/deloitte-python-2-jan-2023/images/django_mvt.png new file mode 100644 index 0000000..ee7c691 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/django_mvt.png differ diff --git a/deloitte-python-2-jan-2023/images/edit-in-workspace.png b/deloitte-python-2-jan-2023/images/edit-in-workspace.png new file mode 100644 index 0000000..0932429 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/edit-in-workspace.png differ diff --git a/deloitte-python-2-jan-2023/images/envdiagram_names_global.png b/deloitte-python-2-jan-2023/images/envdiagram_names_global.png new file mode 100644 index 0000000..c60371f Binary files /dev/null and b/deloitte-python-2-jan-2023/images/envdiagram_names_global.png differ diff --git a/deloitte-python-2-jan-2023/images/envdiagram_names_in_func.png b/deloitte-python-2-jan-2023/images/envdiagram_names_in_func.png new file mode 100644 index 0000000..8c163f7 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/envdiagram_names_in_func.png differ diff --git a/deloitte-python-2-jan-2023/images/files.png b/deloitte-python-2-jan-2023/images/files.png new file mode 100644 index 0000000..89ca86a Binary files /dev/null and b/deloitte-python-2-jan-2023/images/files.png differ diff --git a/deloitte-python-2-jan-2023/images/first_bug.jpg b/deloitte-python-2-jan-2023/images/first_bug.jpg new file mode 100644 index 0000000..0379237 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/first_bug.jpg differ diff --git a/deloitte-python-2-jan-2023/images/fork-repl.png b/deloitte-python-2-jan-2023/images/fork-repl.png new file mode 100644 index 0000000..26a2de9 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/fork-repl.png differ diff --git a/deloitte-python-2-jan-2023/images/global.png b/deloitte-python-2-jan-2023/images/global.png new file mode 100644 index 0000000..d3f3c46 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/global.png differ diff --git a/deloitte-python-2-jan-2023/images/if-order.png b/deloitte-python-2-jan-2023/images/if-order.png new file mode 100644 index 0000000..6eef13b Binary files /dev/null and b/deloitte-python-2-jan-2023/images/if-order.png differ diff --git a/deloitte-python-2-jan-2023/images/if-order2.png b/deloitte-python-2-jan-2023/images/if-order2.png new file mode 100644 index 0000000..39b819b Binary files /dev/null and b/deloitte-python-2-jan-2023/images/if-order2.png differ diff --git a/deloitte-python-2-jan-2023/images/legb.png b/deloitte-python-2-jan-2023/images/legb.png new file mode 100644 index 0000000..86dbafc Binary files /dev/null and b/deloitte-python-2-jan-2023/images/legb.png differ diff --git a/deloitte-python-2-jan-2023/images/list.png b/deloitte-python-2-jan-2023/images/list.png new file mode 100644 index 0000000..33e1bda Binary files /dev/null and b/deloitte-python-2-jan-2023/images/list.png differ diff --git a/deloitte-python-2-jan-2023/images/local.png b/deloitte-python-2-jan-2023/images/local.png new file mode 100644 index 0000000..a8bcdf9 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/local.png differ diff --git a/deloitte-python-2-jan-2023/images/name_value.png b/deloitte-python-2-jan-2023/images/name_value.png new file mode 100644 index 0000000..60cd9c1 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/name_value.png differ diff --git a/deloitte-python-2-jan-2023/images/nasa-key-request.png b/deloitte-python-2-jan-2023/images/nasa-key-request.png new file mode 100644 index 0000000..642a1f8 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/nasa-key-request.png differ diff --git a/deloitte-python-2-jan-2023/images/nasa-key.png b/deloitte-python-2-jan-2023/images/nasa-key.png new file mode 100644 index 0000000..62a2886 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/nasa-key.png differ diff --git a/deloitte-python-2-jan-2023/images/nested-lists-table.png b/deloitte-python-2-jan-2023/images/nested-lists-table.png new file mode 100644 index 0000000..3edaa9d Binary files /dev/null and b/deloitte-python-2-jan-2023/images/nested-lists-table.png differ diff --git a/deloitte-python-2-jan-2023/images/nested_expression_tree.png b/deloitte-python-2-jan-2023/images/nested_expression_tree.png new file mode 100644 index 0000000..1da6a94 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/nested_expression_tree.png differ diff --git a/deloitte-python-2-jan-2023/images/notebook.png b/deloitte-python-2-jan-2023/images/notebook.png new file mode 100644 index 0000000..e83415d Binary files /dev/null and b/deloitte-python-2-jan-2023/images/notebook.png differ diff --git a/deloitte-python-2-jan-2023/images/postman-fork.png b/deloitte-python-2-jan-2023/images/postman-fork.png new file mode 100644 index 0000000..d0df118 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/postman-fork.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_assignment.png b/deloitte-python-2-jan-2023/images/pythontutor_assignment.png new file mode 100644 index 0000000..61c7fe5 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_assignment.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_code.png b/deloitte-python-2-jan-2023/images/pythontutor_code.png new file mode 100644 index 0000000..fb59a4d Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_code.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_code2.png b/deloitte-python-2-jan-2023/images/pythontutor_code2.png new file mode 100644 index 0000000..31ad29a Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_code2.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_conditionals.png b/deloitte-python-2-jan-2023/images/pythontutor_conditionals.png new file mode 100644 index 0000000..9b8e9b3 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_conditionals.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_defstatement.png b/deloitte-python-2-jan-2023/images/pythontutor_defstatement.png new file mode 100644 index 0000000..fb1ec8a Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_defstatement.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_frames.png b/deloitte-python-2-jan-2023/images/pythontutor_frames.png new file mode 100644 index 0000000..58fd292 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_frames.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_frames2.png b/deloitte-python-2-jan-2023/images/pythontutor_frames2.png new file mode 100644 index 0000000..54957c8 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_frames2.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_functioncall.png b/deloitte-python-2-jan-2023/images/pythontutor_functioncall.png new file mode 100644 index 0000000..9d906ef Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_functioncall.png differ diff --git a/deloitte-python-2-jan-2023/images/pythontutor_loops.png b/deloitte-python-2-jan-2023/images/pythontutor_loops.png new file mode 100644 index 0000000..7bc0e45 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/pythontutor_loops.png differ diff --git a/deloitte-python-2-jan-2023/images/replit-edit-in-workspace.png b/deloitte-python-2-jan-2023/images/replit-edit-in-workspace.png new file mode 100644 index 0000000..bcfdd7b Binary files /dev/null and b/deloitte-python-2-jan-2023/images/replit-edit-in-workspace.png differ diff --git a/deloitte-python-2-jan-2023/images/replit-fork.png b/deloitte-python-2-jan-2023/images/replit-fork.png new file mode 100644 index 0000000..3d7ae95 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/replit-fork.png differ diff --git a/deloitte-python-2-jan-2023/images/replit-install-plotly.png b/deloitte-python-2-jan-2023/images/replit-install-plotly.png new file mode 100644 index 0000000..40ade2c Binary files /dev/null and b/deloitte-python-2-jan-2023/images/replit-install-plotly.png differ diff --git a/deloitte-python-2-jan-2023/images/replit-packages-requests.png b/deloitte-python-2-jan-2023/images/replit-packages-requests.png new file mode 100644 index 0000000..5a1d95a Binary files /dev/null and b/deloitte-python-2-jan-2023/images/replit-packages-requests.png differ diff --git a/deloitte-python-2-jan-2023/images/replit-run-code.png b/deloitte-python-2-jan-2023/images/replit-run-code.png new file mode 100644 index 0000000..f76705e Binary files /dev/null and b/deloitte-python-2-jan-2023/images/replit-run-code.png differ diff --git a/deloitte-python-2-jan-2023/images/run-w-args.png b/deloitte-python-2-jan-2023/images/run-w-args.png new file mode 100644 index 0000000..cb46c0e Binary files /dev/null and b/deloitte-python-2-jan-2023/images/run-w-args.png differ diff --git a/deloitte-python-2-jan-2023/images/table.png b/deloitte-python-2-jan-2023/images/table.png new file mode 100644 index 0000000..3fa43df Binary files /dev/null and b/deloitte-python-2-jan-2023/images/table.png differ diff --git a/deloitte-python-2-jan-2023/images/web_application.png b/deloitte-python-2-jan-2023/images/web_application.png new file mode 100644 index 0000000..3a3acf4 Binary files /dev/null and b/deloitte-python-2-jan-2023/images/web_application.png differ diff --git a/deloitte-python-2-jan-2023/index.html b/deloitte-python-2-jan-2023/index.html new file mode 100644 index 0000000..9fe384e --- /dev/null +++ b/deloitte-python-2-jan-2023/index.html @@ -0,0 +1,160 @@ + + + + + + GDI Python 2 + + + +
    + + +
    + +
    +

    + Lesson 7: Review from Python 1 & more reading/writing files +

    + +

    Topics:

    +

    Brief review of Python 1 topics, opening files for reading, writing to files, working with CSV

    + +

    Materials:

    + +
    +
    +

    + Lesson 8: More file operations, argument parsing & list comprehension +

    + +

    Topics:

    +

    File system operations with the OS module, passing arguments to command-line apps with argparse

    + +

    Materials:

    + +
    +
    +

    + Lesson 9: Error handling +

    + +

    Topics:

    +

    Types of errors, Python exception types, handling runtime exceptions with try/except blocks

    + +

    Materials:

    + +
    +
    +

    + Lesson 10: HTTP requests +

    +

    Topics:

    +

    Brief intro to HTTP/REST APIs, making API requests using the requests module, parsing responses

    + +

    Materials:

    + +
    + +
    +

    + Lesson 11: Intro to Python frameworks & getting started with Django +

    + +

    Topics:

    +

    Popular Python frameworks & what to use them for, Django features, and setting up a Django app

    +

    Materials:

    + +
    + + +
    + +
    +

    + Lesson 12: Your own app with Django! +

    + +

    Topics:

    +

    Building on the basic Django setup to create a simple app with backend logic and frontend templates

    + +

    Materials:

    + +
    + +
    + +
    + + diff --git a/deloitte-python-2-jan-2023/intro/intro.html b/deloitte-python-2-jan-2023/intro/intro.html new file mode 100644 index 0000000..168e275 --- /dev/null +++ b/deloitte-python-2-jan-2023/intro/intro.html @@ -0,0 +1,295 @@ + + + + + + Coming soon: Python 2! + + + + + + + + +
    +
    + +
    +

    🐍 Coming soon: Python 2!

    + +
    + Tips for navigating the slides: +
      +
    • Press O or Escape for overview mode.
    • +
    • Visit this link for a nice printable version
    • +
    • Press the copy icon on the upper right of code blocks to copy the code
    • +
    +
    +
    +
    +

    Welcome! A bit about Girl Develop It

    +

    We create welcoming, supportive and accessible environments for women and non-binary adults to learn software development.

    +

    We are dedicated to providing a welcoming and comfortable environment for all to learn coding.
    + Code of conduct

    +
    +
    +

    What does Girl Develop It teach?

    +
      +
    • Web Development +
    • Data Science +
    • UX Design & Research +
    • Workforce Classes +
    • Career-Building Events & Conferences +
    +

    Check out all of our classes & events girldevelopit.com

    +
    +
    +

    Your Instructor

    +
      +
    • Liz Krznarich (she/her)
    • +
    • Technical Lead, DataCite
    • +
    • Many tech hats worn! Fullstack engineer, frontend engineer, technical trainer, graphic designer...
    • +
    • Python, Java, JS (Angular/React/Ember), DevOps (Ansible/Terraform/Puppet)
    • +
    • Fun fact: Degrees in Art and Library Science. First professional job involved hot dog ads.
    • +
    +
    +
    +

    Classroom "rules"

    +
      +
    • I am here for you!
    • +
    • Every question is important
    • +
    • Help each other
    • +
    • Have fun
    • +
    +
    +
    +

    What's in store for Python 2?

    + +

    This may change if we end up needing more or less time for certain topics.

    +
      +
    • Class 7: Review & reading from/writing to files +
    • Class 8: More file operations, argument parsing & list comprehension +
    • Class 9: Error handling +
    • Class 10: HTTP requests +
    • Class 11: Intro to Python frameworks & object-oriented Python +
    • Class 12: Your own app with Django! +
    +

    (note: Python 1 series included classes 1-6)

    +
    +
    +

    Working with files

    +

    Have lots of files you need to combine, extract data from, clean up, rename or format into a nice report? We can do that!

    + Screenshot of files converted to report +
    +
    +

    Errors! Why they happen & what to do about them

    +

    We don't want users (or ourselves) to see mysterious errors at runtime +

    
    +                        Traceback (most recent call last):
    +                        File "", line 1, in 
    +                        TypeError: 'type' object is not iterable
    +                        >>>
    +                    
    +

    We want to provide fallback code or a useful error message +

    
    +                        try:
    +                            for item in list:
    +                                do_really_cool_thing()
    +                        except:
    +                            print("Oh noes! Something went wrong with an item:"")
    +                            print(item)
    +                    
    +
    +
    +

    HTTP requests

    +

    "Hypertext transfer protocol" sounds like it's from 1995, but it's still the way data gets around on the Web!

    +

    We'll learn how to use the requests module to get data from external sources, like APIs

    +
    
    +                        import requests
    +                        r = requests.get('https://api.github.com/users/lizkrznarich')
    +                        print(r.status_code)
    +                        200
    +                        print(r.json())
    +                        {'login': 'lizkrznarich', 'id': 8026886, 'node_id': 'MDQ6VXNlcjgwMjY4ODY=', 'avatar_url': 'https://avatars.githubusercontent.com/u/8026886?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/lizkrznarich', 'html_url': 'https://github.com/lizkrznarich', 'followers_url': 'https://api.github.com/users/lizkrznarich/followers', 'following_url': 'https://api.github.com/users/lizkrznarich/following{/other_user}', 'gists_url': 'https://api.github.com/users/lizkrznarich/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/lizkrznarich/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/lizkrznarich/subscriptions', 'organizations_url': 'https://api.github.com/users/lizkrznarich/orgs', 'repos_url': 'https://api.github.com/users/lizkrznarich/repos', 'events_url': 'https://api.github.com/users/lizkrznarich/events{/privacy}', 'received_events_url': 'https://api.github.com/users/lizkrznarich/received_events', 'type': 'User', 'site_admin': False, 'name': 'Liz Krznarich', 'company': 'DataCite', 'blog': '', 'location': None, 'email': None, 'hireable': None, 'bio': None, 'twitter_username': None, 'public_repos': 17, 'public_gists': 4, 'followers': 10, 'following': 0, 'created_at': '2014-06-30T13:28:04Z', 'updated_at': '2023-01-05T12:47:53Z'}
    +                    
    +
    +
    +

    Building web apps with Django

    +

    Django is a popular framework for building Python web apps quickly

    +

    We'll use it to build a small app that fetches data from an API and displays it in a web page.

    + Screenshot of Django landing page +
    +
    +

    What should I know before starting Python 2?

    + +

    Python 2 builds on Python 1, so you should be familiar with the basics covered in that class:

    +
      +
    • Data types & expressions (strings, integers, floats, booleans) +
    • Data structures (lists, dictionaries, tuples) +
    • Defining functions +
    • Calling functions & methods +
    • Conditionals (if/then/else) +
    • Loops (while & for) +
    +
    +
    +

    Class logistics

    + +
    +
    +

    Questions?

    +
    + +
    +
    + + + + + + + + +