Functions are similar to
objects in
Python
- An object has
a class name and
an address:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person("John", 36)
print(p1)
<__main__.Person object at 0x7f093be7d850>
|
- A function has the
class function and
an address:
# This is how to "create" a function "object":
def f1():
print("Called f1")
print(f1)
<function f1 at 0x7f093c0ba2a0>
|
|
DEMO:
progs/func-as-obj.py
Function as a
parameter
- Functions can have
functions as
parameters:
def f1():
print("Called f1")
def f2(f): # f is a function parameter
f()
f2( f1 )
Called f1
|
- Functions in
Python are
in fact like an
object:
- Functions can be
stored in a
variable
- Functions can be
passed as
a parameter
-
Functions can
also be
returned by
a function !!!
|
|
DEMO:
progs/func-as-param.py
Wrapper functions: returning a function
- Example of
wrapper function:
def w(func):
def wrapper(): # This function is LOCAL to w( )
print("Started")
func()
print("Ended")
return wrapper # Returns a function !
def f1():
print("Hello")
f2 = w(f1) # Pass f1 to w() and receive a NEW function f2
f2() # Call the new function f2()
Started
Hello
Ended
|
|
DEMO:
progs/wrapper.py
The function name is actually a variable
- We can assign a
function to
a function name:
def w(func):
def wrapper(): # This function is LOCAL to w( )
print("Started")
func()
print("Ended")
return wrapper # Returns a function !
def f1():
print("Hello")
f1() Hello
# f1 is a VARIABLE and can be assigned....
f1 = w(f1) # Pass f1 to w() and receive a NEW function
f1() Started Hello Ended
f1 = w(f1) # Pass f1 to w() and receive a NEW function
f1() Started Started Hello Ended Ended
|
|
DEMO:
progs/wrapper2.py
Decorators
- Decorator notation:
def w(func):
def wrapper(): # This function is LOCAL to w( )
print("Started")
func()
print("Ended")
return wrapper # Returns a function !
# Instead of writing:
def f1():
print("Hello")
f1 = w(f1) # Pass f1 to w() and receive a NEW function f2
f1() Started Hello Ended
# We can write: ("decorator notation")
@w
def f2():
print("Hello")
f2() Started Hello Ended
|
|
DEMO:
progs/decorator.py
Using * args and
** kwargs to create
general decorators
- A function with
a parameter will
break the
previous
example:
def w(func):
def wrapper(): # This function is LOCAL to w( )
print("Started")
func() # *** Function has NO parameter !
print("Ended")
return wrapper # Returns a function !
# Instead of writing:
def f1(s):
print(s)
f1 = w(f1) # Pass f1 to w() and receive a NEW function f2
f1("New")
TypeError: w.wrapper() takes 0 positional arguments but 1 was given
# We can write: ("decorator notation")
@w
def f2(s): # Function has 1 parameter
print(s)
f2("New")
|
|
DEMO:
progs/decorator2.py
Using * args and
** kwargs to create
general decorators
-
Solution:
capture the positional args with
*args and
the keyword args with
**kwargs:
def w(func):
def wrapper(*args, **kwargs):
print("Started")
func(*args, **kwargs) # *** Function has general parameters !
print("Ended")
return wrapper # Returns a function !
# Instead of writing:
def f1(s):
print(s)
f1 = w(f1) # Pass f1 to w() and receive a NEW function f2
f1("New") Started New Ended
# We can write: ("decorator notation")
@w
def f2(s): # Function has 1 parameter
print(s)
f2("New") Started New Ended
|
|
DEMO:
progs/decorator3.py
❮
❯