<style> .present { text-align: left; } </style> # Python Data Types & Basic Control Flow ## Week 17 Day 2 --- ## Lecture videos 1 (20 min) Watch: - Python Basics (7:06) - Number Types (9:00) --- ### `print()` We can use `print` to write messages to the console terminal ```python= print("Hello world") ``` Equivalent to `console.log` in JavaScript ```javascript= console.log("Hello world") ``` --- ### Commenting code In Python, comments start with `#` ```python= # this is a comment print("Hello") # can also start in line ``` Just like the `//` in JavaScript ```javascript= // this is a comment console.log("Hello world") // can also start in line ``` --- ### Commenting code Longer comment blocks can use the `"""` syntax ```python= """ You can use three quotes in a row for multiline comments """ ``` Like in JavaScript, where `/* ... */` creates multiline comments ```javascript= /* longer comment more commenting here */ ``` --- ### Number Data Types We'll mostly interact with `int` and `float` types - `int` (integers): counting numbers with no decimal points - `float` (floating point numbers): numbers with decimal places. - They may occasionally have rounding errors, just like JavaScript - see [documentation on floating point arithmetic](https://docs.python.org/3/tutorial/floatingpoint.html) - `complex`: complex numbers --- | Operator | Meaning | Example | |:--------:|:---------------- |:--------------------- | | `+` | addition | `print(10+4) # 14` | | `-` | subtraction | `print(10-4) # 6` | | `*` | multiplication | `print(10*4) # 40` | | `/` | division | `print(10/4) # 2.25` | | `%` | modulo | `print(10%4) # 2` | | `**` | exponent | `print(10**4) # 10000`| | `//` | integer division | `print(10//4) # 2` | --- ### Number Operations - Plus operator (`+`) can be used for both numeric addition and string concatenation - But type conversion between strings and numbers won't happen automatically (unlike JavaScript) ```python= print("hello " + "world") # "hello world" print("hello " + 7) # TypeError # explicitly convert types print("hello" + str(7)) # "hello7" ``` --- ## Exercises 1 (35 minutes) - Hello, Eggs and Spam (5:00) - Plus, Minus, More (5:00) - Fun With Functions (5:00) - Adding Two Numbers (1:00) - Convert Minutes To Seconds (1:00) - Livestock Legs (5:00) - Return Next Number (1:00) - Remainder Of Two Numbers (1:00) - String To Integer (5:00) - By The Power Of... (1:00) --- ## Lecture videos 2 (25 min) Watch: - Simple Formatted Strings (10:19) - Duck Typing (7:26) - Arithmetic With Strings (3:36) --- ### String Data Type - Strings use single quotes (`'`) or double quotes (`"`) - Using three quotes in a row (either `"""` or `'''`) will open a multiline string ```python= my_long_string = ''' you can make longer strings over multiple lines individual quote characters ' " won't end the string ''' ``` --- ### String Interpolation String formatting with `%` operator ```python= word = "hi" num = 6 print("%s is a word. %i is an integer" % (word, num)) # prints "hi is a word. 6 is an integer" ``` --- ### String Interpolation String formatting with `.format()` method (better) ```python= word = "hi" num = 6 print("{stuff} and {number}".format(stuff=word, number=num)) # prints "hi and 6" # positional print("{1} is a value, so is {0}".format(word, num)) ``` --- ### String Interpolation String formatting with `f` strings (best): ```python= word = "hi" num = 6 print(f"{word} and {num}") ``` Most similar to interpolated strings in JavaScript: ```javascript= let word = "hi" let num = 6 console.log(`${word} and ${num}`) ``` --- ### String Arithmetic ```python= a = "a" b = "b" an = "an" print(b + an) print(b + a*7) print(b + an*2 + a) print("$1" + ",000"*3) ``` --- ### String indexing - Use square brackets (`[]`) - Index starts at 0 (like in JavaScript) ```python= print("Spaghetti"[0]) # S print("Spaghetti"[4]) # h ``` - Can use a negative index ```python= print("Spaghetti"[-1]) print("Spaghetti"[-4]) ``` --- ### String indexing Indexing with ranges: the start value is inclusive, the end value is skipped ```python= # indexing with ranges print("Spaghetti"[1:4]) # pag print("Spaghetti"[4:-1]) # hett print("Spaghetti"[4:4]) # (empty string) print("Spaghetti"[:4]) # Spag print("Spaghetti"[:-1]) # Spaghett print("Spaghetti"[1:]) # paghetti print("Spaghetti"[-4:]) # etti ``` --- ### String indexing Out of range values will through errors if you try to access the single value, but they are valid as part of a range. ```python= print("Spaghetti"[15]) # IndexError: string index out of range print("Spaghetti"[-15]) # IndexError: string index out of range print("Spaghetti"[:15]) # Spaghetti print("Spaghetti"[15:]) # (empty string) print("Spaghetti"[-15:]) # Spaghetti print("Spaghetti"[:-15]) # (empty string) print("Spaghetti"[15:20]) # (empty string) ``` --- ### String methods: `.index()` Returns the first index where the substring is found ```python= print("kiwi".index("k")) # 0 print("kiwi".index("m")) # ValueError: substring not found ``` --- ### String methods: `.count()` Returns the number of times the substring is found ```python= print("kiwi".count("k")) # 1 print("kiwi".count("i")) # 2 print("kiwi".count("m")) # 0 ``` --- ### String methods: `.split()` Returns a list (array) of substrings, split on the character (or substring) passed - If no character is passed, a space is used to split ```python= print("Hello World".split()) # ["Hello", "World"] print("Hello World".split(" ")) # ["Hello", "World"] print("i-am-a-dog".split("-")) # ["i", "am", "a", "dog"] ``` --- ### String methods: `.join()` Use a given string to join all the substrings from the list argument - Works in reverse from what you may be used to with JavaScript ```python= print(" ".join(["Hello", "World"])) # "Hello World" # ["Hello", "World"].join(" ") JavaScript print("-".join(["i", "am", "a", "dog"])) # "i-am-a-dog" ``` --- ### String methods: `.upper()` & `.lower()` Transform a string to the specified case - these functions do not mutate the value of the string ```python= a = 'Hello' print(a) # 'Hello' print(a.upper()) # 'HELLO' print(a) # 'Hello' ``` --- ### Duck Typing? From the video - "better to ask forgiveness than permission" - this is a pythonic principle---a fundamental part of control flow in python - but it's not actually Duck Typing - Duck Typing won't really come into play until we're creating our own classes - We'll talk more on Thursday, once we've introduced classes --- ### Control flow with `try/except` blocks Keywords: - `try`: run this code until an exception occurs - `except`: run this code when an exception occurs - `else`: run this code only if no exception occurs - `finally`: run this code no matter what --- ### Control flow with `try/except` blocks ```python= num = 0 try: print("Trying now...") print(4/num) except ZeroDivisionError: print("oops i tried to divide by zero!") finally: print("this happens no matter what") ``` --- ### Control flow with `try/except` blocks Avoid using a bare `except`— you should specify the type of error in almost every case. A "bare `except`" can be dangerous... ```python= while True: try: num = int(input("say a number ")) print(num) break except ValueError: print("try again") ``` --- ## Exercises 2 (15 min) - Fun With Strings (5:00) - Burrrrrp (5:00) - Concatenate Names (1:00) --- ## Lecture Videos 3 (12 min) Watch - Assignment Operators (9:17) --- ### Assignment operators We can use assignment operators (like in JavaScript) to concisely update values ```python= a = 2 a += 3 print(a) # 5 a *= 2 print(a) # 10 ``` But no more `++` or `--` ```python= a++ # SyntaxError: invalid syntax ``` --- ## Lecture Videos 4 (30 minutes) Watch: - The Meaning of Truth (13:22) - Identity vs. Equality Demo (10:50) --- ### Truthiness in Python Falsey values in Python: - 0 (for any number type) - `0`, `0.0`, `0j` - any empty collection - `""`, `[]`, `set()`, `{}`, `range(0)` - `False` - `None` Truthy values in Python: - anything not listed above --- ### Logic Operators We use the keywords `and`, `or`, and `not` in Python instead of `&&`, `||`, and `!` ```python= print(True and False) # False print(True or False) # True print(True and not False) # True ``` --- ### Logical operators Parentheses can group our conditions, just like JavaScript ```python= print(False and (True or True)) # False print((False and True) or True) # True ``` --- ### Short circuiting If we can already determine the overall outcome of a conditional, Python won't bother evaluating the rest of the statement. (JavaScript also has short-circuiting) ```python= False and print("not printed") # does not print False or print("printed #1") # prints "printed #1" True and print("printed #2") # prints "printed #2" True or print("not printed") # does not print ``` --- ### While loops While loops follow a very similar structure to JavaScript. ```python= i = 0 while i < 5: print(f"{i}. Hello, world.") i += 1 print("You've printed 5 times. Goodbye.") ``` --- ### Loop keywords: `continue` and `break` - `continue`: goes to the next iteration of the loop - `break`: exits out of the loop completely ```python= i = 0 while True: print(f"{i}. Hello, world.") if i < 4: i += 1 continue print("You've printed 5 times. Goodbye.") break ``` --- ### Identity vs. Equality - in JavaScript: `==` is bad, `===` is good - in Python: `is` and `==` are both useful, just for different things - Equality is not about typechecking, it's just about whether the values are the same ```python= my_int = 4 my_float = 4.0 # check if the values are the same print(my_int == my_float) # True # check if the values are the same and check type print(my_int == my_float and isinstance(my_int, float)) # False ``` --- ### When to use `==` (equality): - Most of the time! - Whenever you are comparing two values to see if they are the same - strings, numbers, lists, dictionaries, etc ```javascript= // javascript version console.log({ gorilla: "large" } === { gorilla: "large" }) // false ``` ```python= # python version print({"gorilla": "large"} == {"gorilla": "large"}) # True ``` --- ### When to use `is` (identity) [1/3]: 1. For checking if a value is not `None` ```python= a = [] if a: print("a is truthy") else: print("a is falsey") # prints "a is falsey" if a is not None: print("a is not None") # prints "a is not None" else: print("a is None") ``` --- ### When to use `is` (identity) [2/3]: 2. For checking is `True` / `False` ```python= a = 1 print(a == True) # don't do this print(a is True) ``` --- ### When to use `is` (identity) [3/3]: 3. For checking whether two objects are the same object ```python= print([] == []) # True print([] is []) # False a = [] b = a print(a is b) # True b.append(5) print(a) # [5] ``` --- ### What is the "identity" `id()` returns the “identity” of an object. - Integer which is guaranteed to be unique and constant for this object during its lifetime (i.e. while the program is running) ```python= print(id(None)) # 4315260920 print(id(None)) # 4315260920 a = None print(id(a)) # 4315260920 ``` --- ## Practices 4 (40 min) - Double That Penny (5:00) - Numeric Equality (1:00) - Using and (1:00) - Split On Capitals (10:00) - Count Characters In String (5:00) - Factorial (5:00) - Is Divisible By 5 (1:00) - Is The Last Character N? (5:00) - Same Number Of Characters? (1:00) --- ## Lecture Videos 5 (14 min) Watch: - Functions in Python (8:28) - Functions Returning Functions (2:00) --- ### Python Functions - We use the `def` keyword to define a function followed by: - The name of the function - The arguments that it accepts - A new block identified as `:` and indent the next line ```python= def is_even(num): return num % 2 == 0 print(is_even(5)) # False print(is_even(2)) # True ``` --- ### Python Scoping - Scoping is done at the function level - In JS, we had block scopes - In PY, our `if` statements do not create new scopes ```python= def make_a_five(): y = 5 return y if True: x = 10 print(x) #10 # `x` was created in the global scope print(y) # NameError: name 'y' is not defined # `y` was created in the scope of the make_a_five function ``` --- ### Lambda Functions - For simple one-line functions, we can also use a lambda, which takes in: - Arguments on left side of `:` - Returns the value resulting from the right side of the `:` ```python= is_even = lambda num: num % 2 == 0 print(is_even(8)) # True ``` --- ### PEP-8 Style Guidlines - The use case of lambdas is when you are going to use a function once without assigning it - Assigning a lambda to a variable essentially duplicates the purpose of the def keyword, hence it is not pythonic --- ### Functions Returning Functions ```python= def order_pizza(pizza_type): order = f"I would like a {pizza_type} pizza" print(pizza_type) return lambda topping_type: order + f" with {topping_type}." sausage_pizza = order_pizza("sausage") # prints from line 3: "sausage" print(sausage_pizza("bell pepper")) # "I would like a sausage pizza with bell pepper." ``` --- ### Summary Practices (50 minutes) - Valid Hex Code (10:00) - First Before Second (10:00) - Sequence of Numbers (30:00) ### Summary Quizzes (20 minutes) - Python Documentation Quiz (5:00) - Arithmetic Operators (5:00) - Strings? (5:00) - Short Circuit (5:00)