<jupyter_start><jupyter_text>Introduction to Python Day 2* Organization: Centre for Data, Culture & Society, University of Edinburgh* Instructor: <NAME>* Date: 25 February 2022Today we'll continue using Jupyter Notebooks to practice using the programming language Python, covering functions, methods, modules, conditionals, error handling, loops and iteration, and recursion. Functions vs. MethodsRecall from last class that functions help programmers like us write code more efficiently. Sometimes, especially as your coding tasks become more complex, you'll find that you want to reuse the same code, or slight variations of the same code, again and again. Functions let you reuse code without having to rewrite it every time you want to use it. By storing lines of code you've written within the bounds of a function that you name, you can refer to those lines of code by the name to reuse that code.Methods work the same way, allowing you to reuse code, but it's more common to reuse methods that are built into Python than it is to write your own methods. Though both functions and methods allow you to reuse code for more efficient programming, but they are a little different.To understand this difference, let's first write a function ourselves:<jupyter_code># def subtractThenMultiply(no1, no2, no3):
#     difference = no1 - no2
#     product = difference * no3
#     return product

def subtractThenMultiply(no1, no2, no3=10):
    difference = no1 - no2
    product = difference * no3
    return product
A = 2
B = 3
C = 4
subtractThenMultiply(A, B)
result = subtractThenMultiply(A,B,C)
result
result = subtractThenMultiply(A, B)
print('{first} minus {second} time {third} equals {fourth}'.format(first=A,second=B,third=10,fourth=result))<jupyter_output>2 minus 3 time 10 equals -10<jupyter_text>Notice that when we want to use the function, we put the **parameters** A, B and C on which to apply the function inside the parentheses that follow the function's name:`functionName(parameter1, parameter2, parameter3)` Now let's try using a method that Python gives us: `lower()`<jupyter_code>x = "Isn't Python SO MUCH fun?!"
x.lower()
x
x = x.lower()
x<jupyter_output><empty_output><jupyter_text>What happened to the string we stored in **variable** x?What difference do you notice about how we used the method lower() versus how we used the function `subtractThenMultiply()`?The *syntax* is different: a method follows the thing on which you want to apply the method, separated by a period, while a function's parentheses contain the thing(s) on which you want to apply the function.`some_data.methodName() vs. functionName(parameter1, parameter2, parameter3)`  ModulesLet's practice using other built-in libraries of code that Python gives us called **modules**. Modules aren't as commonly used as methods, as they apply to more specific programming tasks, so they're not pre-loaded with Python in a Jupyter Notebook. Don't worry, though, they're easy to load! All we have to do is write in a code cell:`import moduleName`There are lots of modules available to you in Python: check out [this index](https://docs.python.org/3/py-modindex.html) for the complete list!<jupyter_code>import string
string.punctuation
string.ascii_lowercase
string.ascii_uppercase
alphabet = string.ascii_lowercase+string.ascii_uppercase
print(alphabet)
print(f'Alphabet: {string.ascii_lowercase}{string.ascii_uppercase}')
datetime.datetime.now()<jupyter_output><empty_output><jupyter_text>Whoops!  In order to use a module, we need to first *import* it into our Notebook:<jupyter_code>import datetime
datetime.datetime.now()<jupyter_output><empty_output><jupyter_text>Hmm.  That doesn't look very nice.The datetime module has ways to specify the format of dates, though, so let's try using some of those to see if we can get a more readable version of today's date:<jupyter_code>today = datetime.datetime.now()
today.strftime("%d/%m/%Y")<jupyter_output><empty_output><jupyter_text>That looks much better!`strftime()` is the string format time module: we can specify the date or time format we would like to use inside quotes.  `%d` refers to the day of the month, `%m` refers to the month written as a two-digit number, and `%Y` refers to the year written as a four-digit number.  What do you think `%y` would give us?  `%b`?  `%B`?Let's see...<jupyter_code>print(today.strftime("%d %b %y"))
print(today.strftime("%B %d, %Y"))
print(today.strftime("Time This Code Executed: %H:%M:%S"))<jupyter_output>Time This Code Executed: 11:22:36<jupyter_text>For more date and time formatting options to input into `strftime()`, visit [this W3 Schools resource](https://www.w3schools.com/python/python_datetime.asp).  ConditionalsConditionals are useful in functions where you have code you may want to reuse but, depending on what data you're looking at, different lines of code should be run. The key terms when writing conditionals are `if`, `elif` (for 'else if'), and `else`.<jupyter_code># if/elif/else

year = 2032
# year = None
# year = '2021'

if year < 2022:
    future = False  # Boolean values: True, False
elif year == 2022:
    time = False
else:
    future = True
print(future)

# if year < 2022:
#     time = "past"
# elif year == 2022:
#     time = "present"
# else:
#     future = "future"
# print(future)
def inFuture(year):
    future = False
    try:
        if year > 2022:
            future = True
    except TypeError:
        return 'Please input an integer to provide a valid year for evaluation.'
    return future
y1 = None
y2 = 1900
y3 = 2032
print(inFuture(y1))
print(inFuture(y2))
print(inFuture(y3))<jupyter_output>Please input an integer to provide a valid year for evaluation.
False
True<jupyter_text>Loops and IterationLoops and iteration let you execute a task repeatedly for a set period. You can use loops and iteration to look at data or change data.<jupyter_code>years = [y1, y2, y3]  
# Note: the `years` variable is storing three variables in a List, which is a data type we'll cover next class!
for y in years:
    print(y)
x = 10
while x > -1:
    print(x)
    x = x - 1

# Infinite loop - press the stop buttom (the square to the right of the 'Run' button) to stop the code!
# x = 10
# while x >= -1:
#     print(x)
#     x = x+x - 1<jupyter_output>10
9
8
7
6
5
4
3
2
1
0<jupyter_text>RecursionFunctions that call themselves.<jupyter_code>def doubleNTo10(n):
    if n >= 10:
        return "Done!"
    else:
        print(n)
        return doubleNTo10(n+n)
doubleNTo10(2)<jupyter_output>2
4
8
{'fraction_non_alphanumeric': 0.0876438986953185, 'fraction_numerical': 0.019033000767459708, 'mean_word_length': 4.661164205039096, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 37, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '424491', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 2069, 'n_tokens_neox': 1915, 'n_words': 845, 'path': 'ClassNotebooks/IntroToPython_Day2.ipynb', 'repo_name': 'DCS-training/python-intro', 'size': '6520'}