<class 'list'>
True
False
January 27, 2025
<class 'list'>
True
False
mylist = []
creates an empty listtype(mylist)
returns the type of the listisinstance
returns True
or False
for provided typeisinstance(mylist, list)
checks if mylist
is a list
def generator_example(n):
for i in range(n):
yield i
print(type(generator_example))
print(type(generator_example(5)))
<class 'function'>
<class 'generator'>
type
shows that functions and generators have their own typesreturn
and yield
influence a function’s behavior?type
functionu = (3,4)
v = (3,6)
def add(a, b):
return (a[0] + b[0], a[1] + b[1])
def subtract(a,b):
return (a[0] - b[0], a[1] - b[1])
def dot(a, b):
return (a[0] * b[0] + a[1] * b[1])
def norm(a):
return (a[0] * a[0] + a[1] * a[1]) ** 0.5
def isvertical(a):
return a[0] == 0
print(norm(u))
print(add(u,v))
print(u + v)
print(isvertical(subtract(v, u)))
5.0
(6, 10)
(3, 4, 3, 6)
True
tuple
for encoding stateclass Vector:
def __init__(self, x, y):
try:
self.x = float(x)
self.y = float(y)
except ValueError:
self.x = 0.0
self.y = 0.0
def norm(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
def __add__(self, other):
newx = self.x + other.x
newy = self.y + other.y
return Vector(newx, newy)
def __str__(self):
return "({:.2f}, {:.2f})".format(self.x, self.y)
u = Vector(3,4)
v = Vector(3,6)
print(u + v)
(6.00, 10.00)
Vector
, what is the state and behavior? What are the strengths and weaknesses of this approach to representing vectors? How could this approach lead to program defects?Triangle
Triangle
object have?Triangle
object?Square
Square
object have?Square
object?__init__
and __str__
?Square
and a Triangle
?Polygon
class is a superclass of Triangle
and Square
Triangle
and Square
classes are subclasses of Polygon
Polygon
class is a generalization of Triangle
and Square
Triangle
and Square
to the Polygon
SuperclassTriangle
and Polygon
and also Square
and Polygon
Python is a dynamically typed language
Python uses duck typing to determine types
Remember the silly adage of “If it walks like a duck and quacks like a duck, then it must be a duck”
Inheritance is not only way to create an “is-a” relationship!
Yet, inheritance makes the “is-a” relationship explicit
Triangle
and Square
to the Polygon
Superclasspolygon
parameter can be any object with a sides
methodclass MyLimitedList:
def __init__(self):
self._L = []
def append(self, item):
self._L.append(item)
def __getitem__(self, index):
return self._L[index]
limited = MyLimitedList()
limited.append(1)
limited.append(10)
limited.append(100)
print(limited[2])
100
MyLimitedList
class is composed of a list called _L
import timeit, f
n = int(1e6); num_exec = 1
for func in filter(lambda f: f.startswith('loop'), sorted(dir(f))):
print('====== Timing function called:', func)
print(getattr(f, func).__doc__)
t = timeit.timeit(stmt='f.%s(n)' % func,
number=num_exec, globals=globals())
per_loop = round(t / n * 1e9)
print('Time: %ins, Theoretical max bandwidth: %.2fMB/s' %
(per_loop, 1000 / per_loop))
====== Timing function called: loop_0_empty
Run empty loop n times.
Time: 14ns, Theoretical max bandwidth: 71.43MB/s
====== Timing function called: loop_1_f
Run loop with empty function n times.
Time: 37ns, Theoretical max bandwidth: 27.03MB/s
====== Timing function called: loop_2_f_twice
Run loop calling empty function twice per loop, n times.
Time: 61ns, Theoretical max bandwidth: 16.39MB/s
f.py
"""f.py: A module to benchmark Python function call overhead."""
def f():
pass
def loop_0_empty(n):
"""Run empty loop n times."""
for i in range(n):
pass
def loop_1_f(n):
"""Run loop with empty function n times."""
for i in range(n):
f()
def loop_2_f_twice(n):
"""Run loop calling empty function twice per loop, n times."""
for i in range(n):
f()
f()
import timeit, g
n = int(1e6); num_exec = 1
for func in filter(lambda g: g.startswith('loop'), sorted(dir(g))):
print('====== Timing function called:', func)
print(getattr(g, func).__doc__)
t = timeit.timeit(stmt='g.%s(n)' % func,
number=num_exec, globals=globals())
per_loop = round(t / n * 1e9)
print('Time: %ins, Theoretical max bandwidth: %.2fMB/s' %
(per_loop, 1000 / per_loop))
====== Timing function called: loop_3_g
Run loop with empty function taking args, n times.
Time: 62ns, Theoretical max bandwidth: 16.13MB/s
====== Timing function called: loop_5_g_arg
Run loop with empty function passing an arg, n times.
Time: 80ns, Theoretical max bandwidth: 12.50MB/s
====== Timing function called: loop_6_g_kwarg
Run loop with empty function passing a kwarg, n times.
Time: 84ns, Theoretical max bandwidth: 11.90MB/s
g.py
"""g.py: A module to benchmark Python function call overhead."""
def g(*args, **kwargs):
pass
def loop_3_g(n):
"""Run loop with empty function taking args, n times."""
for i in range(n):
g()
def loop_5_g_arg(n):
"""Run loop with empty function passing an arg, n times."""
for i in range(n):
g(n)
def loop_6_g_kwarg(n):
"""Run loop with empty function passing a kwarg, n times."""
for i in range(n):
g(n=n)
function-calls
timer.py
and observe the resultsf.py
and g.py
Algorithmology