def dispatch(data): # function object
print(data)
return list(data)
def subdispatch(func, seq):
data = func(seq)
print(data)
data = dispatch("ACGTGGC")
print(data)
func = dispatch # function object can be assigned to a name
func("TTTTT")
data2 = func("CCCCC")
print(data2)
subdispatch(dispatch, "CATCATCAT") # function object can be sent as an argument
def outer(msg):
statement = msg
def inner():
print(statement)
return inner
func1 = outer("something else")
func2 = outer("another thing")
func1()
func2()
def original_function():
print("running original code")
def decorator_function(func):
def wrapper_function():
print("do something before")
func()
print("do something after")
return wrapper_function
new_function = decorator_function(original_function)
new_function()
def original_function(data1, data2):
print(f"running w/ values {data1}, {data2}")
def decorator_function(func):
def wrapper_function(*arg, **kwargs):
print("do something before")
func(*arg, **kwargs)
print("do something after")
return wrapper_function
new_function = decorator_function(original_function)
new_function("happy", 1)
def original_function(data1, data2):
print(f"running w/ values {data1}, {data2}")
class decorator_class(object):
def __init__(self, some_function):
self.some_function = some_function
def __call__(self, *args, **kwargs):
print("do something before")
self.some_function(*args, **kwargs)
print("do something after")
new_function = decorator_class(original_function)
new_function("happy", 1)
import time
def debug_timer(some_function):
def wrapper_function(*args, **kwargs):
t1 = time.time()
some_function(*args, **kwargs)
t2 = time.time()
print(f"elapsed time: {t2 - t1} s")
return wrapper_function
@debug_timer # @ is a symbol that allows access to the debug_timer
def original_function(data1, data2):
print(f"orig func with ({data1},{data2})")
# t1 = time.time()
# original_function("happy", 1)
# t2 = time.time()
# print(f"elapsed time: {t2 - t1} s")
# test_function = debug_timer(original_function)
# test_function("happy", 1)
original_function("happy", 1)
original_function([row for row in range(0,100000)], 1)
@ is a decorator that extends the functionality of an existing function or class
class Point:
def __init__(self, x=0.0, y=0.0):
self.x = x
self.y = y
@property
def r(self):
from math import sqrt
return sqrt(self.x ** 2 + self.y ** 2)
@property
def theta(self):
from math import atan, pi
return atan(self.y / self.x) / pi * 180
def print_euclid(self):
print(f"({self.x}, {self.y})")
def print_polar(self):
print(f"({self.r},{self.theta})")
point1 = Point(2, 3)
point1.print_euclid()
point1.print_polar()
point1.x = 5
point1.print_euclid()
point1.print_polar()
class Point:
def __init__(self, x=0.0, y=0.0):
self.x = x
self.y = y
@property
def r(self):
from math import sqrt
return sqrt(self.x ** 2 + self.y ** 2)
@property
def theta(self):
from math import atan, pi
return atan(self.y / self.x) / pi * 180
def print_euclid(self):
print(f"({self.x}, {self.y})")
def print_polar(self):
print(f"({self.r}, {self.theta})")
def print_origin(self):
print(f"({self.x0}, {self.y0})")
@classmethod
def set_origin(cls, x=0.0, y=0.0): # cls represents the class object
cls.x0 = x
cls.y0 = y
@staticmethod
def distance(point1, point2):
from math import sqrt
return sqrt((point2.x-point1.x)**2 + (point2.y-point1.y)**2)
point1 = Point(2, 3)
point2 = Point(4, 5)
point1.print_euclid()
point2.print_euclid()
# print(f"({point1.x},{point1.y})")
# print(f"({point2.x},{point2.y})")
point1.set_origin(5, 5)
point1.print_origin()
point2.print_origin()
point3 = Point(6, 6)
point3.print_origin()
print(Point.distance(point1, point2))