# by default, only the result of the last expression in a cell is displayed after evaluation.
# the following forces display of *all* self-standing expressions in a cell.
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
if-else statements¶age=16
if age>=16:
print("old enough to drive")
print("not old enough to vote")
print("in high school")
old enough to drive not old enough to vote in high school
age=15
if age>=16:
print("old enough to drive")
else:
print("NOT old enough to drive")
NOT old enough to drive
from random import randint
score = randint(50, 100)
grade = None
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
elif score >= 70:
grade = 'C'
elif score >= 60:
grade = 'D'
else:
grade = 'E'
print(score, grade)
61 D
#modules
import random
random
dir(random)
<module 'random' from 'C:\\Users\\bauerm\\anaconda3\\lib\\random.py'>
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI', '_Sequence', '_Set', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_accumulate', '_acos', '_bisect', '_ceil', '_cos', '_e', '_exp', '_inst', '_log', '_os', '_pi', '_random', '_repeat', '_sha512', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', 'choice', 'choices', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'triangular', 'uniform', 'vonmisesvariate', 'weibullvariate']
while loops¶f0 = 0
f1 = 1
while f0 < 100:
print(f0)
f0, f1 = f1, f0+f1
0 1 1 2 3 5 8 13 21 34 55 89
i = 0
to_find = 10
while i < 5:
i += 1
if i == to_find:
print('Found; breaking early')
break
else:
print('Not found; terminated loop')
Not found; terminated loop
i = 0
to_find = 10
while i < 100:
i += 1
if i == to_find:
print('Found; breaking early')
break
else:
print('Not found; terminated loop')
Found; breaking early
?random.randint
?pandas
Object `pandas` not found.
raise Exception('Boom!')
--------------------------------------------------------------------------- Exception Traceback (most recent call last) <ipython-input-2-19c2dbb533f1> in <module> ----> 1 raise Exception('Boom!') Exception: Boom!
raise NotImplementedError()
--------------------------------------------------------------------------- NotImplementedError Traceback (most recent call last) <ipython-input-3-03b9be105f74> in <module> ----> 1 raise NotImplementedError() NotImplementedError:
try:
raise Exception('Boom')
except:
print('Exception encountered!')
Exception encountered!
try:
x = 1/0
except LookupError as e:
print('LookupError:', e)
except ArithmeticError as e:
print('ArithmeticError:', e)
except Exception as e:
print(e)
finally: #optional
print('Done')
ArithmeticError: division by zero Done
for loops (iteration)¶for x in range(10): # for every element in the sequence type List String range tuple set dictionary
print(x)
# range(singleArgument) counts from 0 to singleArgument-1
# range(arg1, arg2() counts from arg1 to arg2-1
for x in range(3, 7): # for every element in the sequence type List String range tuple set dictionary
print(x)
0 1 2 3 4 5 6 7 8 9 3 4 5 6
for x in range(3, 7,2): # for every element in the sequence type List String range tuple set dictionary
print(x) # 3rd arg is step
3 5
for x in range(10, 3,-3): # for every element in the sequence type List String range tuple set dictionary
print(x) # 3rd arg is step
10 7 4
for x in range(3, 10,-3): # for every element in the sequence type List String range tuple set dictionary
print(x) # 3rd arg is step
for i in range(9, 81, 9):
print(i)
9 18 27 36 45 54 63 72
for x in range(11.5): # for every element in the sequence type List String range tuple set dictionary
print(x)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-12-4567bec1368d> in <module> ----> 1 for x in range(11.5): # for every element in the sequence type List String range tuple set dictionary 2 3 print(x) TypeError: 'float' object cannot be interpreted as an integer
for c in 'hello world':
print(c)
h e l l o w o r l d
to_find = 50
for i in range(100):
if i == to_find:
break
else: # only run if loop is not exited early
print('Completed loop')
to_find = 150
for i in range(100):
if i == to_find:
break
else: # only run if loop is not exited early
print('Completed loop')
Completed loop
iter and next)¶r = range(10)
it = iter(r) # iterators walk a sequenced type, pointer initially to the first element
r
it
range(0, 10)
<range_iterator at 0x2119b207370>
type(it)
range_iterator
next(it) # next is a function on iter objects, gets the current element and increments the iter
0
next(it)
next(it)
next(it)
next(it)
next(it)
next(it)
next(it)
1
2
3
4
5
6
7
next(it)
8
next(it)
9
next(it)
--------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-23-7eda7e8b947f> in <module> ----> 1 next(it) StopIteration:
it = iter(r)
while True:
try:
x = next(it)
print(x)
except StopIteration:
break
# for x in r:
# print(x)
0 1 2 3 4 5 6 7 8 9
it = iter(r)
while True:
try:
x = next(it)
y = next(it)
print(x, y, x+y)
except StopIteration:
break
0 1 1 2 3 5 4 5 9 6 7 13 8 9 17
it1 = iter(r)
it2 = iter(r)
print(next(it1))
print(next(it1))
print(next(it1))
print(next(it2))
print(next(it1))
0 1 2 0 3
def foo():
pass
import math
def quadratic_roots(a, b, c):
disc = b**2-4*a*c
if disc < 0:
return None
else:
return (-b+math.sqrt(disc))/(2*a), (-b-math.sqrt(disc))/(2*a)
quadratic_roots(1, -5, 6) # eq = (x-3)(x-2)
(3.0, 2.0)
quadratic_roots(1, -2, 6) #imaginary roots
quadratic_roots(a=1, b=-5, c=6)
(3.0, 2.0)
quadratic_roots(c=6, a=1, b=-5)
(3.0, 2.0)
quadratic_roots(1, -5)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-38-e987ba98279e> in <module> ----> 1 quadratic_roots(1, -5) TypeError: quadratic_roots() missing 1 required positional argument: 'c'
import math
def quadratic_roots1(a, b, c=1):
disc = b**2-4*a*c
if disc < 0:
return None
else:
return (-b+math.sqrt(disc))/(2*a), (-b-math.sqrt(disc))/(2*a)
quadratic_roots1(1, -5, 6)
quadratic_roots1(1, -5)
(3.0, 2.0)
(4.7912878474779195, 0.20871215252208009)
def create_character(name, race, hitpoints, ability):
print('Name:', name)
print('Race:', race)
print('Hitpoints:', hitpoints)
print('Ability:', ability)
create_character('Legolas', 'Elf', 100, 'Archery')
Name: Legolas Race: Elf Hitpoints: 100 Ability: Archery
def create_character(name, race='Human', hitpoints=100, ability=None):
print('Name:', name)
print('Race:', race)
print('Hitpoints:', hitpoints)
if ability:
print('Ability:', ability)
create_character('Michael')
Name: Michael Race: Human Hitpoints: 100
def create_character(name, race='Human', hitpoints=100, abilities=()): # () is an empty tuple
print('Name:', name)
print('Race:', race)
print('Hitpoints:', hitpoints)
if abilities:
print('Abilities:')
for ability in abilities:
print(' -', ability)
create_character('Gimli', race='Dwarf')
Name: Gimli Race: Dwarf Hitpoints: 100
create_character('Gandalf', hitpoints=1000)
Name: Gandalf Race: Human Hitpoints: 1000
name
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-46-9bc0cb2ed6de> in <module> ----> 1 name NameError: name 'name' is not defined
create_character('Aragorn', abilities=('Swording', 'Healing')) # tuple is immutable collection ( )
Name: Aragorn Race: Human Hitpoints: 100 Abilities: - Swording - Healing
# another way to load multiple abilities NOT in a tuple already is with multiple/variable
# number of arguments * prefix on an argument means it is a variable number of arguments
def create_character(name, *abilities, race='Human', hitpoints=100):
print('Name:', name)
print('Race:', race)
print('Hitpoints:', hitpoints)
if abilities:
print('Abilities:')
for ability in abilities:
print(' -', ability)
create_character('Michael')
Name: Michael Race: Human Hitpoints: 100
create_character('Michael', 'Coding', 'Teaching', 'Sleeping', hitpoints=25)
Name: Michael Race: Human Hitpoints: 25 Abilities: - Coding - Teaching - Sleeping
create_character('Michael', 'Coding', 'Teaching', 'Sleeping', 25)
Name: Michael Race: Human Hitpoints: 100 Abilities: - Coding - Teaching - Sleeping - 25
def create_character1(name, *abilities, race='Human', hitpoints=100):
print(abilities)
print('Name:', name)
print('Race:', race)
print('Hitpoints:', hitpoints)
if abilities:
print('Abilities:')
for ability in abilities:
print(' -', ability)
create_character1('Michael', 'Coding', 'Teaching', 'Sleeping', hitpoints=25)
('Coding', 'Teaching', 'Sleeping')
Name: Michael
Race: Human
Hitpoints: 25
Abilities:
- Coding
- Teaching
- Sleeping
def foo():
print('Foo called')
bar = foo
bar()
Foo called
def foo(f): #argument f is a function because I call it like a function f()
f()
def bar():
print('Bar called')
foo(bar)
Bar called
foo = lambda: print('Anonymous function called') # defining a function without the full def syntax
foo()
Anonymous function called
f = lambda x,y: x+y # arguments separated by commas : function code
f(1,2)
3
def my_map(f, it): #filter(subset), map(translate), reduce(combine?
for x in it:
print(f(x))
my_map(lambda x: x*2, range(1,10))
2 4 6 8 10 12 14 16 18
for x in map(lambda x: x*2, range(1,10)):
print(x)
2 4 6 8 10 12 14 16 18
for x in map(lambda x: x*2, 'matt'):
print(x)
mm aa tt tt
def foo():
print('Foo called')
type(foo)
function
dir(foo)
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
foo.__call__() # same as foo()
Foo called
class Foo:
pass
Basic Class Example
class Foo:
# we do not need to declare instance attributes
def __init__(self, newX=1):
self.x=newX # any variable prefaces with "self" is an instance attribute
print('I got constructed')
# start a variable with __ to make it private self.__y
z = Foo() # z.__init__()
z
z.x
xx = Foo(5)
xx
xx.x
I got constructed
<__main__.Foo at 0x2b99cea0e80>
1
I got constructed
<__main__.Foo at 0x2b99ce943d0>
5
class Foo:
# we do not need to declare instance attributes
def __init__(self, newX=1):
self.x=newX # any variable prefaces with "self" is an instance attribute
print('I got constructed')
# start a variable with __ to make it private self.__y
#tostring equivalent
def __repr__(self): # unformatted version of attributes MUST RETURN A STRING
return str(self.x)
def __str__(self): # stringification TO STRING formatted version of attributes
# MUST RETURN A STRING
return "x="+str(self.x)
def __eq__(self, that): # called two Foo objects z==xx z is self xx is that
# xx.__eq__(z) xx is self z is that
return self.x==that.x
a = Foo(37)
a #repr
print(a) #str
a==z
I got constructed
37
x=37
False
Inheritance Example
class Shape:
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
def __str__(self):
return self.name.upper()
def area(self):
raise NotImplementedError()
s = Shape('circle')
s
print(s)
circle
CIRCLE
str(s)
'CIRCLE'
s.area()
--------------------------------------------------------------------------- NotImplementedError Traceback (most recent call last) <ipython-input-18-88799e7f1f86> in <module> ----> 1 s.area() <ipython-input-13-24ae96e78afe> in area(self) 10 11 def area(self): ---> 12 raise NotImplementedError() NotImplementedError:
class Circle(Shape): #inheritance syntax "Circle isa Shape"
def __init__(self, radius):
super().__init__('circle') #super goes up in the inheritance to parent method
# setting the self.name attribute for a Circle object
self.radius = radius # adding another attribute to Circle object
def area(self):
return 3.14 * self.radius ** 2
c = Circle(5.0)
c #repr
c.area()
circle
78.5
class Circle(Shape):
countCircles=0
def __init__(self, radius):
super().__init__('circle')
self.radius = radius
Circle.countCircles+=1
def area(self):
return 3.14 * self.radius ** 2
def __eq__(self, that): # c==d maps to == operator
if isinstance(that, Circle):
return self.radius==that.radius
else:
return false
# def eq(self, that): # does not map to any standard python operator or method
# pass
# # a.eq(b)
def __str__(self): # maps to str() function
return "circle with radius " + str(self.radius)
def __add__(self, that): #new circle object with added radii maps to + operator
if isinstance(that, Circle):
return Circle(self.radius+that.radius) # calling Circle constructor
else:
return none
# class method, @staticmethod
@staticmethod
def bar(): # not no self argument
print(Circle.countCircles)
c1 = Circle(2.0)
c2 = Circle(4.0)
c3 = Circle(2.0)
c1.area()
c1, c2, c3
c1 == c2
c1 == c3
str(c1 + c2)
_
Circle.bar()
12.56
(circle, circle, circle)
False
True
'circle with radius 6.0'
'circle with radius 6.0'
4
Recall: All immutable sequences support the common sequence operations. For many sequence types, there are constructors that allow us to create them from other sequence types.
z='hello'
z[2]
z[-1]
'l'
'o'
z[0]='M'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-39-5d46709a2e6f> in <module> ----> 1 z[0]='M' TypeError: 'str' object does not support item assignment
z+' world'
z
'hello world'
'hello'
range(10) # if one argument, start at 0 and go to arg-1
range(0, 10)
str(range(10))
'range(0, 10)'
for i in range(10):
print(i)
0 1 2 3 4 5 6 7 8 9
range(10, 20) #start at 10, go to 19
for i in range(10, 20):
print(i)
range(10, 20)
10 11 12 13 14 15 16 17 18 19
range(20, 50, 5) #start at 20, increment by 5 to 49
for i in range(20, 50, 5):
print(i)
range(20, 50, 5)
20 25 30 35 40 45
for z in range(10, 0, -1):
print(z)
10 9 8 7 6 5 4 3 2 1
range(10)+ range(5)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-47-c2e058c678a2> in <module> ----> 1 range(10)+ range(5) TypeError: unsupported operand type(s) for +: 'range' and 'range'
max(range(5))
4
() # indexed collection of items, immutable parens around a commas seperated list to make a tuple
()
len(())
0
(1, 2, 3)
(1, 2, 3)
('a', 10, False, 'hello')
('a', 10, False, 'hello')
tuple(range(10))
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
tuple('hello')
('h', 'e', 'l', 'l', 'o')
str((1,2,3))
'(1, 2, 3)'
str(range(5))
'range(0, 5)'
z=tuple('hello')
z
z[3]
min(z)
('h', 'e', 'l', 'l', 'o')
'l'
'e'
z[0]='m'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-60-9ab83c5d0519> in <module> ----> 1 z[0]='m' TypeError: 'tuple' object does not support item assignment
z['l']
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-61-1c266ee813aa> in <module> ----> 1 z['l'] TypeError: tuple indices must be integers or slices, not str
z[-4]
'e'
a=(1,2,3)
b=("cat", "dog")
xx=a+b #create a new tuple
a
b
xx
(1, 2, 3)
('cat', 'dog')
(1, 2, 3, 'cat', 'dog')
xx[1]
xx[-1]
2
'dog'
xx[-1][2]
'g'
7 + 5
#7 + (5,)
7+tuple((5,))
12
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-74-4076a337e69b> in <module> 1 7 + 5 2 #7 + (5,) ----> 3 7+tuple((5,)) TypeError: unsupported operand type(s) for +: 'int' and 'tuple'