# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python [conda root]
#     language: python
#     name: conda-root-py
# ---

# + [markdown] slideshow={"slide_type": "slide"}
# # Python Basics

# + [markdown] slideshow={"slide_type": "slide"}
# ## Variables
# -

# - A variable is just a name for a value,
#     such as `x`, `my_variable`, or `variable_1`
# - Python's variables must begin with a letter and are **case sensitive**
# - We can create a new variable by assigning a value to it using `=`

# + slideshow={"slide_type": "subslide"}
x = 1

# + slideshow={"slide_type": "fragment"}
x

# + slideshow={"slide_type": "subslide"}
y = 2
z = x + y
z

# + slideshow={"slide_type": "subslide"}
w

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Naming
#
# - Variable names in Python can contain alphanumerical characters `a-z`, `A-Z`, `0-9` and some special characters such 
#     as `_`. Normal variable names must start with a letter. 
# - By convention, variable names start with a lower-case letter, and Class names start with a capital letter. 
# - In addition, there are a number of Python keywords that cannot be used as variable names. These keywords are:
#
#         and, as, assert, break, class,
#         continue, def, del, elif, else, 
#         except, exec, finally, for, from,
#         global, if, import, in, is, lambda, 
#         not, or, pass, print, raise, 
#         return, try, while, with, yield
#
# - _Note_: Be aware of the keyword `lambda`, which could easily be a natural variable name in a scientific program. But 
#     being a keyword, it cannot be used as a variable name.

# + [markdown] slideshow={"slide_type": "slide"}
# ## Data types

# + [markdown] slideshow={"slide_type": "subslide"}
# Since Python is **dynamically typed**, it automatically sets the types of your variables upon assignment

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Integers

# + slideshow={"slide_type": "-"}
x = 1
type(x)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Floats

# + slideshow={"slide_type": "-"}
y = 2.
type(y)

# + slideshow={"slide_type": "fragment"}
y = 2e0
print(y, type(y))
# -

3.17e1

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Booleans
# -

a = True
b = False
type(a)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Strings

# + slideshow={"slide_type": "-"}
z = '3'
type(z)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Checking Type

# + slideshow={"slide_type": "fragment"}
a = 1
type(a)

# + slideshow={"slide_type": "fragment"}
b = 2.
type(b) is int

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Type casting
# - Only variables of the same type can be combined
# - Where possible, Python will automatically cast one variable to be the same type as another to make them compatible

# + slideshow={"slide_type": "fragment"}
x = 1
print(type(x))

# + slideshow={"slide_type": "fragment"}
y = 2.
print(type(y))

# + slideshow={"slide_type": "fragment"}
print(type(int(y)))

# + slideshow={"slide_type": "fragment"}
print(type(x+y))

# + slideshow={"slide_type": "subslide"}
z = '3'
w = x + z

# + slideshow={"slide_type": "fragment"}
w = x + int(z)
print(w, type(w))

# + slideshow={"slide_type": "subslide"}
print(bool(0))
print(bool(1))

# + slideshow={"slide_type": "fragment"}
print(bool(0.))
print(bool(1.))

# + slideshow={"slide_type": "fragment"}
print(bool('0'))
print(bool('1'))

# + slideshow={"slide_type": "fragment"}
print(bool('True'))
print(bool('False'))

# + [markdown] slideshow={"slide_type": "slide"}
# ## Operators
#
# Operators are defined as "constructs which can manipulate the values of operands"...

# + [markdown] slideshow={"slide_type": "subslide"}
# Arithmetic operators:
# - `+` 
# - `-` 
# - `*` 
# - `/`
# - `//` (integer division)
# - `**` (power)
# - `%` (modulus)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Addition

# + slideshow={"slide_type": "-"}
1 + 1

# + slideshow={"slide_type": "fragment"}
1. + 1.

# + slideshow={"slide_type": "fragment"}
1 + 1.

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Subtraction

# + slideshow={"slide_type": "-"}
5 - 2

# + slideshow={"slide_type": "fragment"}
5. - 2.

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Order of operations

# + slideshow={"slide_type": "fragment"}
5 - 3 + 1

# + slideshow={"slide_type": "fragment"}
5 - (3 + 1)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Multiplication

# + slideshow={"slide_type": "-"}
2 * 4

# + slideshow={"slide_type": "fragment"}
2. * 4

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Division

# + slideshow={"slide_type": "-"}
3 / 4

# + slideshow={"slide_type": "fragment"}
3. / 4.

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Integer division

# + slideshow={"slide_type": "-"}
3 // 4

# + slideshow={"slide_type": "fragment"}
5 // 4

# + slideshow={"slide_type": "fragment"}
5. // 4.

# + slideshow={"slide_type": "subslide"}
10 - 2 * 3

# + slideshow={"slide_type": "fragment"}
10 - (2 * 3)

# + slideshow={"slide_type": "fragment"}
(10 - 2) * 3

# + slideshow={"slide_type": "fragment"}
((2 + 3) - 1) * 2

# + slideshow={"slide_type": "subslide"}
0 / 1

# + slideshow={"slide_type": "fragment"}
1 / 0

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Power
# -

2**3

# + slideshow={"slide_type": "fragment"}
2.**3

# + slideshow={"slide_type": "fragment"}
2. ** 3

# + slideshow={"slide_type": "fragment"}
2. * * 3

# + slideshow={"slide_type": "fragment"}
# Note: don't try to use the caret (^) for power in Python! 
# For the curious: https://docs.python.org/2/reference/expressions.html#binary-bitwise-operations
2^3

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Modulus
# -

5 % 4

# + slideshow={"slide_type": "fragment"}
4 % 4

# + slideshow={"slide_type": "fragment"}
16 % 4

# + slideshow={"slide_type": "fragment"}
17 % 4

# + [markdown] slideshow={"slide_type": "slide"}
# ## Comparisons
#
# [Comparisons](https://docs.python.org/2/reference/expressions.html#not-in) are operators which evaluate properties 
# of their operands and always return either `True` or `False`

# + [markdown] slideshow={"slide_type": "subslide"}
# Common comparisons:
# - `<`
# - `>`
# - `==`
# - `>=`
# - `<=`
# - `!=`

# + slideshow={"slide_type": "subslide"}
1 < 2

# + slideshow={"slide_type": "fragment"}
a = 1 < 2
print(a, type(a))

# + slideshow={"slide_type": "subslide"}
2 == 2

# + slideshow={"slide_type": "fragment"}
2 == 2.

# + slideshow={"slide_type": "subslide"}
2 != 2.

# + slideshow={"slide_type": "fragment"}
2 != 1

# + slideshow={"slide_type": "subslide"}
3 <= 4

# + slideshow={"slide_type": "fragment"}
3 <= 3

# + slideshow={"slide_type": "fragment"}
3 <= 2.9

# + slideshow={"slide_type": "subslide"}
1 < 2 < 3

# + slideshow={"slide_type": "fragment"}
2 <= 2 < 3

# + slideshow={"slide_type": "fragment"}
2 <= (2 < 3)

# + [markdown] slideshow={"slide_type": "subslide"}
# `is` and `is not` check whether two things point to the same object, not just equality

# + slideshow={"slide_type": "fragment"}
1 is 1

# + slideshow={"slide_type": "fragment"}
1 is 1.

# + slideshow={"slide_type": "subslide"}
x = 1
y = 1
x is y

# + slideshow={"slide_type": "fragment"}
x = 1.
y = 1
x is y

# + slideshow={"slide_type": "fragment"}
x = 1.
y = 1.
x is y

# + slideshow={"slide_type": "fragment"}
x = 1.
y = 1.
x == y

# + slideshow={"slide_type": "fragment"}
x = 1.
y = x
x is y

# + [markdown] slideshow={"slide_type": "subslide"}
# ### [Boolean operations](https://docs.python.org/2/reference/expressions.html#boolean-operations)

# + [markdown] slideshow={"slide_type": "fragment"}
# - `and`: `x and y` first evaluates `x`
#     * if `x` is false, its value is returned
#     * otherwise, `y` is evaluated and the resulting value is returned

# + [markdown] slideshow={"slide_type": "fragment"}
# - `or`: `x or y` first evaluates `x`
#     * if `x` is true, its value is returned
#     * otherwise, `y` is evaluated and the resulting value is returned

# + [markdown] slideshow={"slide_type": "fragment"}
# - `not`: yields `True` if its argument is false, `False` otherwise

# + [markdown] slideshow={"slide_type": "subslide"}
# ### `and`

# + slideshow={"slide_type": "-"}
True and False

# + slideshow={"slide_type": "fragment"}
True and True

# + slideshow={"slide_type": "fragment"}
1 and True

# + slideshow={"slide_type": "fragment"}
1 and False

# + slideshow={"slide_type": "fragment"}
True and 0

# + slideshow={"slide_type": "fragment"}
bool(True and 0)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### `or`

# + slideshow={"slide_type": "-"}
True or False

# + slideshow={"slide_type": "fragment"}
False or True

# + slideshow={"slide_type": "fragment"}
1 or False

# + [markdown] slideshow={"slide_type": "subslide"}
# ### `not`

# + slideshow={"slide_type": "fragment"}
True is not False

# + slideshow={"slide_type": "fragment"}
not True

# + slideshow={"slide_type": "fragment"}
not 2

# + slideshow={"slide_type": "fragment"}
not 0

# + slideshow={"slide_type": "fragment"}
1 is not 2

# + slideshow={"slide_type": "fragment"}
x = 1
y = 1.
x is not y

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Combining boolean operations

# + slideshow={"slide_type": "-"}
1 < 2 < 3

# + slideshow={"slide_type": "fragment"}
(1 < 2) and (2 < 3)

# + slideshow={"slide_type": "fragment"}
(1 < 2) and (1 > 2)

# + slideshow={"slide_type": "fragment"}
0 is not 1 and 2 is not 3

# + slideshow={"slide_type": "fragment"}
0 is 1 or 2 is 2

# + slideshow={"slide_type": "fragment"}
(0 is 1) or (2 is 2)

# + [markdown] slideshow={"slide_type": "slide"}
# ## Fun with strings
# -

s = 'hello world'
type(s)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### String indexing

# + slideshow={"slide_type": "-"}
len(s)

# + slideshow={"slide_type": "fragment"}
s[1]

# + slideshow={"slide_type": "fragment"}
s[0]

# + slideshow={"slide_type": "subslide"}
s[len(s)-1]

# + slideshow={"slide_type": "fragment"}
s[-1]

# + [markdown] slideshow={"slide_type": "subslide"}
# ### String replacement
# -

s.replace('hello', 'goodbye')

# + slideshow={"slide_type": "fragment"}
s.replace('l', 'L')

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Slicing
#
# You can pull out different chunks of the string using `[start:end:step]` 
# - `start` defaults to 0
# - `end` defaults to `len(string)-1` (i.e. the last character)
# - `step` defaults to 1

# + slideshow={"slide_type": "fragment"}
s[0:5]

# + slideshow={"slide_type": "fragment"}
s[:5]

# + slideshow={"slide_type": "fragment"}
s[6:]

# + slideshow={"slide_type": "fragment"}
s[:]

# + slideshow={"slide_type": "fragment"}
s[::1]

# + slideshow={"slide_type": "fragment"}
s[::2]

# + [markdown] slideshow={"slide_type": "subslide"}
# ### String concatenation
# -

'hel' + 'lo'

# + slideshow={"slide_type": "fragment"}
s[:5] + s[6:]

# + slideshow={"slide_type": "fragment"}
'he' + 11 + 0

# + slideshow={"slide_type": "fragment"}
'he' + str(11) + str(0)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### String formatting
#
# - Enables you to combine strings however you'd like
# - Extremely powerful, so see the [docs](https://docs.python.org/3.6/library/string.html#format-string-syntax) for
#     more details

# + slideshow={"slide_type": "fragment"}
print('hello', 'world')

# + slideshow={"slide_type": "fragment"}
'{} {}'.format('hello', 'world')

# + slideshow={"slide_type": "fragment"}
'{1} {0}'.format('hello', 'world')

# + slideshow={"slide_type": "fragment"}
x = 'everybody'
'{} {}'.format('hello', x)

# + slideshow={"slide_type": "fragment"}
from math import pi
'pi is {:.3f}'.format(pi)

# + slideshow={"slide_type": "fragment"}
'π is {:.3f}'.format(pi)

# + slideshow={"slide_type": "fragment"}
number = 1.0
superlative = 'loneliest'
'{num:g} is the {adj} number'.format(adj=superlative, num=number)

# + [markdown] slideshow={"slide_type": "slide"}
# ## Lists
#
# - A list is similar to a string in that it's a collection of objects
# - However, in Python a list can contain objects of any type

# + slideshow={"slide_type": "subslide"}
a = [1,2,3]
a

# + slideshow={"slide_type": "fragment"}
type(a)

# + slideshow={"slide_type": "fragment"}
['hello', 'world']

# + slideshow={"slide_type": "fragment"}
[1, 'love']

# + slideshow={"slide_type": "subslide"}
a = [1, 'two', 3.]

# + slideshow={"slide_type": "fragment"}
print(a[0])
print(a[1])
print(a[2])

# + slideshow={"slide_type": "fragment"}
len(a)

# + slideshow={"slide_type": "fragment"}
a[3]

# + slideshow={"slide_type": "fragment"}
a[-1]

# + slideshow={"slide_type": "fragment"}
type(a[-1])

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Nested lists
# -

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

# + slideshow={"slide_type": "fragment"}
a[0]

# + slideshow={"slide_type": "fragment"}
a[1]

# + slideshow={"slide_type": "fragment"}
a[0][1]

# + slideshow={"slide_type": "fragment"}
a[1][:]

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Range
# -

start = 5
stop = 15
step = 2
range(start, stop, step)

# + slideshow={"slide_type": "fragment"}
list(range(start, stop, step))

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Strings and lists
# -

a = list('hello world')
a

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Modifying lists
# -

a[0] = 'H'
a

# + slideshow={"slide_type": "fragment"}
a[6] = 'W'
a

# + slideshow={"slide_type": "fragment"}
a.append('!')
a

# + slideshow={"slide_type": "fragment"}
a.insert(5, ',')
a

# + slideshow={"slide_type": "fragment"}
a.remove('l')
a

# + slideshow={"slide_type": "subslide"}
''.join(a)

# + slideshow={"slide_type": "fragment"}
'\n'.join(a)

# + slideshow={"slide_type": "fragment"}
print('\n'.join(a))

# + slideshow={"slide_type": "subslide"}
b = []
b.append(1)
b.append(2)
b

# + slideshow={"slide_type": "fragment"}
b.reverse()
b

# + slideshow={"slide_type": "fragment"}
b.sort()
b

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Checking inside of lists
# -

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

# + slideshow={"slide_type": "fragment"}
2 in c

# + slideshow={"slide_type": "fragment"}
7 in c

# + slideshow={"slide_type": "fragment"}
c.index(3)

# + slideshow={"slide_type": "fragment"}
c.index(10)

# + slideshow={"slide_type": "fragment"}
print(c)
c.remove(2)
print(c)

# + slideshow={"slide_type": "fragment"}
print(c)
popped = c.pop(c.index(5))
print(c, popped)

# + [markdown] slideshow={"slide_type": "slide"}
# ## Tuples
#
# Tuples are like lists but **immutable**, meaning they cannot be changed
# -

d = (1,2)
d

# + slideshow={"slide_type": "fragment"}
d[0]

# + slideshow={"slide_type": "fragment"}
d[0] = 5

# + slideshow={"slide_type": "fragment"}
e = tuple([1,2,3])
e

# + [markdown] slideshow={"slide_type": "slide"}
# ## Dictionaries
#
# - Dictionaries are also like lists, except that instead of values being indexed by their order they're indexed by keys
# - Each element is a key-value pair
# - The syntax for dictionaries is `{key1 : value1, ...}`
# -

{'a': 1, 'b': 2}

# + slideshow={"slide_type": "fragment"}
{1: 'hello', 'two': 'world'}

# + slideshow={"slide_type": "fragment"}
d = {'a': 1, 'b': 2, 'c': 3}
d

# + slideshow={"slide_type": "fragment"}
d['d'] = 4
d

# + slideshow={"slide_type": "fragment"}
d['c']

# + slideshow={"slide_type": "fragment"}
x = 'c'
d[x]

# + slideshow={"slide_type": "fragment"}
param = {'mass': 5.0, 'acceleration': 3.2}
param['force'] = param['mass'] * param['acceleration']
param

# + [markdown] slideshow={"slide_type": "slide"}
# ## Control flow
#
# - `if`, `elif` (else if), and `else`
# - Blocks begin with `if condition:` and are then indented below
# - Convention is 4 spaces of indentation

# + slideshow={"slide_type": "subslide"}
if True: 
    print('hi')

# + slideshow={"slide_type": "fragment"}
 if False:
    print('bye')   

# + slideshow={"slide_type": "fragment"}
if True:
    print('hi')
else:
    print('bye')

# + slideshow={"slide_type": "subslide"}
x = 0
if x < 1:
    print('{} is less than 1'.format(x))
elif x > 1:
    print('{} is greater than 1'.format(x))
else:
    print('I guess {} *is* 1?'.format(x))

# + slideshow={"slide_type": "fragment"}
x = 1
if x < 1:
    print('{} is less than 1'.format(x))
elif x > 1:
    print('{} is greater than 1'.format(x))
else:
    print('I guess {} *is* 1?'.format(x))

# + slideshow={"slide_type": "fragment"}
x = 2
if x < 1:
    print('{} is less than 1'.format(x))
elif x > 1:
    print('{} is greater than 1'.format(x))
else:
    print('I guess {} *is* 1?'.format(x))

# + slideshow={"slide_type": "subslide"}
a = 1
if a == 1:
    a = 2
elif a == 2:
    a = 3
else:
    a = 4
a

# + slideshow={"slide_type": "fragment"}
a = 2
if a == 1:
    a = 2
elif a == 2:
    a = 3
else:
    a = 4
a

# + slideshow={"slide_type": "fragment"}
a = 7
if a == 1:
    a = 2
elif a == 2:
    a = 3
else:
    a = 4
a

# + [markdown] slideshow={"slide_type": "slide"}
# ## Loops

# + [markdown] slideshow={"slide_type": "subslide"}
# ### `for` loops
# -

for x in [1,2,3]:
    print(x)

# + slideshow={"slide_type": "fragment"}
for x in range(3):
    print(x)

# + slideshow={"slide_type": "fragment"}
for x in ['hello', 'world']:
    print(x)

# + slideshow={"slide_type": "fragment"}
for x in 'hello world':
    print(x)

# + slideshow={"slide_type": "subslide"}
for x in range(11):
    sq = x**2
    print('{x} squared is {sq}!'.format(x=x, sq=sq))

# + slideshow={"slide_type": "fragment"}
from math import sqrt
for x in range(101):
    rt = sqrt(x)
    if rt == round(rt):
        print('{x} is {rt:g} squared!'.format(x=x, rt=rt))

# + [markdown] slideshow={"slide_type": "subslide"}
# ### `while` loops
# - `while` loops keep executing until they evalute to `False`
# - Be careful not to create an infinite loop!
#     * Use `Ctl+C` (or `Ctl+D`) if you do...

# + slideshow={"slide_type": "fragment"}
x = 0
while x < 5:
    print(x)
    x = x + 1

# + slideshow={"slide_type": "fragment"}
y = 0
while y < 5:
    print(y)
    y += 1

# + slideshow={"slide_type": "fragment"}
z = 5
while z:
    print(z)
    z -= 1

# + [markdown] slideshow={"slide_type": "subslide"}
# ### List comprehensions
# -

[x for x in range(11)]

# + slideshow={"slide_type": "fragment"}
[x**2 for x in range(11)]

# + slideshow={"slide_type": "fragment"}
['{num} squared is {sq}'.format(num=x, sq=x**2) for x in range(11)]

# + slideshow={"slide_type": "subslide"}
squares = {x: x**2 for x in range(11)}
print(squares)

# + slideshow={"slide_type": "fragment"}
squares[5]

# + slideshow={"slide_type": "fragment"}
for key, value in squares.items():
    print('{k} is the square root of {v}'.format(k=key, v=value))

# + [markdown] slideshow={"slide_type": "slide"}
# ## Modules
#
# - The Python Language Reference: http://docs.python.org/2/reference/index.html
# - The Python Standard Library: http://docs.python.org/2/library/
#
# To use a module in a Python program it first has to be imported. A module can be imported using the `import` statement. For example, to import the module `math`, which contains many standard mathematical functions, we can do:

# + slideshow={"slide_type": "subslide"}
import math

# + [markdown] slideshow={"slide_type": "subslide"}
# $ \cos(2 \pi) = 1 $
# -

math.cos(2. * math.pi)

# + [markdown] slideshow={"slide_type": "fragment"}
# $ \cos(\frac{\pi}{2}) = 0 $
# -

math.cos(math.pi / 2.)

# + slideshow={"slide_type": "fragment"}
# https://docs.python.org/2/tutorial/floatingpoint.html
round(math.cos(math.pi / 2.), 10)

# + [markdown] slideshow={"slide_type": "subslide"}
# Importing from modules
# -

from math import cos, pi
cos(2. * pi)

# + [markdown] slideshow={"slide_type": "subslide"}
# `import *`
# -

from math import *
sin(2. * pi)

# + slideshow={"slide_type": "subslide"}
dir(math)[10:20]

# + slideshow={"slide_type": "fragment"}
math.

# + slideshow={"slide_type": "subslide"}
help(math.log)

# + slideshow={"slide_type": "fragment"}
math.log(math.e)

# + slideshow={"slide_type": "fragment"}
math.log(10., 10.)

# + slideshow={"slide_type": "fragment"}
print(3.**2)
print(math.pow(3,2))

# + slideshow={"slide_type": "fragment"}
print(math.e**3.)
print(math.exp(3.))


# + [markdown] slideshow={"slide_type": "slide"}
# ## Functions
#
# - Functions are reusable and flexible bits of Python code
# - Functions are **scoped** - they have access to global variables, but variables created inside of them are local to the function and invisible outside of it
#
#         def func_name(x):
#             return x**2

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Simple functions
# -

def print_hello():
    print('hello')


# + slideshow={"slide_type": "fragment"}
print_hello()


# + slideshow={"slide_type": "fragment"}
def print_hello(name):
    ''' Prints "hello, {name}".'''
    print('hello, {}'.format(name))

print_hello('world')

# + slideshow={"slide_type": "fragment"}
print_hello()


# + slideshow={"slide_type": "fragment"}
def print_hello(name='buddy'):
    print('hello, {}'.format(name))


# + slideshow={"slide_type": "fragment"}
print_hello('world')

# + slideshow={"slide_type": "fragment"}
print_hello()


# + [markdown] slideshow={"slide_type": "subslide"}
# ### Returning values
# -

def sq_print(x):
    ''' Prints the square of x (x^2) '''
    print(x**2)


# + slideshow={"slide_type": "fragment"}
sq_print(3)

# + slideshow={"slide_type": "fragment"}
three_sq = sq_print(3)

# + slideshow={"slide_type": "fragment"}
print(three_sq)

# + slideshow={"slide_type": "fragment"}
type(three_sq)

# + slideshow={"slide_type": "fragment"}
sq_print(3) * 5


# + slideshow={"slide_type": "subslide"}
def sq(x):
    ''' Returns the square of x (x^2)'''
    return x**2


# + slideshow={"slide_type": "fragment"}
sq(3)

# + slideshow={"slide_type": "fragment"}
three_sq = sq(3)
print(three_sq)

# + slideshow={"slide_type": "fragment"}
type(three_sq)

# + slideshow={"slide_type": "fragment"}
sq(3) * 5


# + slideshow={"slide_type": "subslide"}
def sq_with_print(x):
    ''' Returns the square of x (x^2) and prints it '''
    s = x**2
    print('{x} squared is {s}'.format(x=x, s=s))
    return s


# + slideshow={"slide_type": "fragment"}
sq_with_print(5)

# + slideshow={"slide_type": "fragment"}
s = sq_with_print(5)
print(s)
print(type(s))


# + [markdown] slideshow={"slide_type": "subslide"}
# ### Returning multiple values

# + slideshow={"slide_type": "-"}
def rectangle(w, h):
    ''' Given a width `w` and height `h`, returns the area and perimeter of the corresponding rectangle '''
    area = w * h
    perim = 2 * (w + h)
    return area, perim


# + slideshow={"slide_type": "fragment"}
rectangle(5, 10)

# + slideshow={"slide_type": "fragment"}
my_rect = rectangle(5, 10)
print(type(my_rect))
print(my_rect[0])

# + slideshow={"slide_type": "fragment"}
area, perim = rectangle(5, 10)
print(type(area))
print(area)


# + slideshow={"slide_type": "fragment"}
def rectangle(w, h):
    ''' Given a width `w` and height `h`, returns the area and perimeter of the corresponding rectangle in a dict '''
    area = w * h
    perim = 2 * (w + h)
    return {'area': area, 'perim': perim}


# + slideshow={"slide_type": "fragment"}
rectangle(7, 8)

# + slideshow={"slide_type": "fragment"}
my_rect = rectangle(7, 8)
print(my_rect['area'])


# + slideshow={"slide_type": "fragment"}
def rectangle(w, h):
    ''' Given a width w and height h, returns some info about the corresponding rectangle '''
    area = w * h
    perim = 2 * (w + h)
    return {'w': w,
            'h': h,
            'area': area, 
            'perim': perim}


# + slideshow={"slide_type": "fragment"}
rectangle(3, 4)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Keyword args

# + slideshow={"slide_type": "fragment"}
from math import pow
# pow?

# + slideshow={"slide_type": "fragment"}
def my_pow(x, y=2):
    ''' Return x to the power of y, where y defaults to 2 '''
    return x**y


# + slideshow={"slide_type": "fragment"}
my_pow(3, 2)

# + slideshow={"slide_type": "fragment"}
my_pow(3)

# + slideshow={"slide_type": "fragment"}
my_pow(x=3, y=2)

# + slideshow={"slide_type": "fragment"}
my_pow(y=2, x=3)

# + [markdown] slideshow={"slide_type": "subslide"}
# ### Function scope

# + slideshow={"slide_type": "fragment"}
a = 1
def make_a_two():
    ''' Try to change the value of a to 2 '''
    a = 2


# + slideshow={"slide_type": "fragment"}
print(a)

# + slideshow={"slide_type": "fragment"}
make_a_two()
print(a)


# + slideshow={"slide_type": "fragment"}
def make_a_two():
    ''' Try to change the value of a to 2 '''
    a = 2
    print('The value of a is {}'.format(a))


# + slideshow={"slide_type": "fragment"}
make_a_two()

# + slideshow={"slide_type": "fragment"}
print(a)

# + slideshow={"slide_type": "subslide"}
global_a = 5


# + slideshow={"slide_type": "fragment"}
def print_global_a():
    ''' Print out the value of global_a '''
    print('global_a contains {}'.format(global_a))


# + slideshow={"slide_type": "fragment"}
print_global_a()


# + slideshow={"slide_type": "fragment"}
def print_global_a():
    ''' Print out the value of global_a '''
    global_a = 7
    print('global_a contains {}'.format(global_a))


# + slideshow={"slide_type": "fragment"}
print_global_a()

# + slideshow={"slide_type": "fragment"}
print(global_a)

# + [markdown] slideshow={"slide_type": "slide"}
# ## Exercise 2
#
# - Open [Lecture 2/Exercise 2.ipynb](./Exercise 2.ipynb) using your Jupyter notebook server and follow the instructions
# - You can check your solutions in [Lecture 2/Exercise 2 - Solutions.ipynb](./Exercise 2 - Solutions.ipynb)

# + [markdown] slideshow={"slide_type": "slide"}
# # References
#
# - Slide materials inspired by and adapted from [<NAME>](https://github.com/fonnesbeck/HealthPolicyPython) and [<NAME>](https://github.com/jrjohansson/scientific-python-lectures)

StarcoderdataJupyterScriptsDedupFiltered