decorator example
@app.route('/home')
def index_page():
pass
Slide 6
Slide 6 text
Some points to note:
1) Functions can be nested
Slide 7
Slide 7 text
Functions can be nested [1]
functions can be defined within functions
def calc(a, b):
def add(a, b):
return a + b
return add(a, b) * 2
print(calc(2, 2))
Slide 8
Slide 8 text
Functions can be nested [2]
functions can be defined within functions multiple times
def calc(a, b):
def add(a, b):
return a + b
def minus(a, b):
return a - b
return add(a, b) * 2
print(calc(2, 2))
#8
Slide 9
Slide 9 text
Functions can be nested [3]
functions can be defined within functions at multiple levels
def do_this():
def calc(a, b):
def add(a, b):
return a+b
return add(a, b) * 2
return calc(1, 3)
print(do_this())
# 8
Slide 10
Slide 10 text
Some points to note:
2) Functions can take functions as
arguments
Slide 11
Slide 11 text
Functions can take functions as arguments [1]
a normal function
def print_these():
print('----')
print('....')
print('----')
Slide 12
Slide 12 text
Functions can take functions as arguments [2]
def print_these():
print('----')
print('....')
print('----')
calling / executing it
print_these()
the ( ) calls the function
Slide 13
Slide 13 text
Functions can take functions as arguments [3]
implementing a fuction to execute other functions. it actually calls
the function we pass in as argument
def execute(f):
f()
applying
def print_these():
print('----')
print('....')
print('----')
execute(print_these) # same as print_these()
# ----
# ....
# ----
Slide 14
Slide 14 text
Functions can take functions as arguments [4]
we can also retrieve values
def name():
return 'moris'
def view_value(v):
print('the value is', v())
view_value(name)
# the value is moris
Slide 15
Slide 15 text
Some points to note:
3) Functions can return functions
Slide 16
Slide 16 text
Functions can return functions [1]
returning a fuction:
def x():
def y():
print(3)
return y
calling
x()()
# 3
Slide 17
Slide 17 text
Functions can return functions [2]
to avoid this (bit ugly)
x()()
we do
func = x()
func()
Slide 18
Slide 18 text
Functions can return functions [3]
example of use
def welcome_message():
def first_part():
return '------'
def last_part():
return '******'
def body():
return 'welcome to our program'
def main():
print(first_part())
print(body())
print(last_part())
return main
w = welcome_message()
w()
Slide 19
Slide 19 text
Functions can return functions [4]
prints out
# ------
# welcome to our program
# ******
Slide 20
Slide 20 text
Some points to note:
4) Functions can take functions as
arguments
Slide 21
Slide 21 text
Getting arguments passed: positional [1]
we can get all arguments passed using *args
def s(*args):
return args
print(s(1, 2, 3))
print(s(1, 2))
print(s(1))
# (1, 2, 3)
# (1, 2)
# (1,)
Slide 22
Slide 22 text
Getting arguments passed: positional [2]
but we can change *args to anything like *canne
def s(*canne):
return canne
print(s(1, 2, 3))
print(s(1, 2))
print(s(1))
# (1, 2, 3)
# (1, 2)
# (1,)
Slide 23
Slide 23 text
Getting arguments passed: positional [3]
can be useful in the case of
def add(*nums):
return sum(nums)
print(add(1, 2, 3, 4, 5))
print(add(100, 400, 1000))
# 15
# 1500
Slide 24
Slide 24 text
Getting arguments passed: keyword [1]
kwargs allows us to get all keyword arguments passed
def s(**kwargs):
return kwargs
print(s(name='me', age=5, country='mauritius'))
# {'name': 'me', 'age': 5, 'country': 'mauritius'}
Slide 25
Slide 25 text
Getting arguments passed: keyword [2]
as with *args we can change the name to **keyword_arguments
def s(**keyword_arguments):
return keyword_arguments
print(s(name='me', age=5, country='mauritius'))
# {'name': 'me', 'age': 5, 'country': 'mauritius'}
Slide 26
Slide 26 text
We can also mix them
def view_args(*args, **keyw_args):
print(args)
print(keyw_args)
view_args(1, 2, 3, name='me', town='pl')
# (1, 2, 3)
# {'name': 'me', 'town': 'pl'}
Slide 27
Slide 27 text
Some points to note:
4) Functions can be reassigned names
Slide 28
Slide 28 text
Functions can be reassigned names [1]
we can change function names by reassignment
def add(x, y):
return x + y
addition = add
print(addition(2, 3))
# 5
Slide 29
Slide 29 text
Functions can be reassigned names [2]
still works if we delete original
def add(x, y):
return x + y
addition = add
del add
print(addition(2, 3))
# 5
Slide 30
Slide 30 text
In enters the skeleton
Slide 31
Slide 31 text
In enters the skeleton
let us take this piece of code
def quote(text):
return '<<{}>>'.format(text)
def indent(text):
return '> {}'.format(text)
print(indent(quote('abc')))
# > <>
#
# quote('abc') -> '<>'
# indent(quote('abc')) -> '> <>'
Slide 32
Slide 32 text
In enters the skeleton
we can also write it as
def quote(text):
return '<<{}>>'.format(text)
def indent(q):
def dummy(text):
return '> {}'.format(
q(text)
)
return dummy
print(
indent(quote)('i am here')
)
# > <>
Slide 33
Slide 33 text
In enters the skeleton
which is equivalent to:
def indent(q):
def dummy(text):
return '> {}'.format(
q(text)
)
return dummy
@indent
def quote(text):
return '<<{}>>'.format(text)
print(quote('the sun is rising'))
neater
Slide 34
Slide 34 text
Chaining decorators
Slide 35
Slide 35 text
Chaining operators [1]
let's say we want to get
# ----
# > <>
# ----
we just add another function
def enclose(f):
def dummy(text):
return '----\n{}\n----'.format(
f(text)
)
return dummy
and just call
@enclose
where decorators are used: @staticmethod [1]
let's take a simple class
import math
class Calcs:
def add(self, x, y):
return x + y
def hypotenuse(self, x, y):
return math.sqrt((x**2) + (y**2))
c = Calcs()
print(c.hypotenuse(3, 4))
# 5.0
functions not related together
Slide 45
Slide 45 text
where decorators are used: @staticmethod [2]
adding @staticmethod
import math
class Calcs:
@staticmethod
def add(x, y):
return x + y
def hypotenuse(self, x, y):
return math.sqrt((x**2) + (y**2))
c = Calcs()
print(c.add(1, 2))
# 3
isolated from class, using another method/var results in error
Slide 46
Slide 46 text
where decorators are used: @staticmethod [3]
use of @staticmethod
isolate function
group related functions under a name space
visually telling purpose of function
Slide 47
Slide 47 text
@classmethod
Slide 48
Slide 48 text
where decorators are used: @classmethod [1]
syntax
@classmethod
def method_name(var_holding_classs, argument ...
Slide 49
Slide 49 text
where decorators are used: @classmethod [2]
demo
import math
class Person:
@classmethod
def say_hi(cls, name):
return 'hi ' + name
print(Person.say_hi('doe'))
# hi doe
Slide 50
Slide 50 text
@property
Slide 51
Slide 51 text
where decorators are used: @property [1]
another way of customising getters, setters and deleters
class Car:
def __init__(self):
self._wheel = None
@property
def wheel(self):
return self._wheel
@wheel.setter
def wheel(self, number):
self._wheel = number
@wheel.getter
def wheel(self):
return self._wheel
@wheel.deleter
def wheel(self):
del self._wheel
Slide 52
Slide 52 text
nissan = Car()
nissan.wheel = 4
print(nissan.wheel)
#4
but if getter changed
@wheel.getter
def wheel(self):
return self._wheel + 1
and printed
nissan = Car()
nissan.wheel = 4
print(nissan.wheel)
we'd get 5
Slide 53
Slide 53 text
where decorators are used: @property [2]
same as __set__ , __get__ and __del__
Slide 54
Slide 54 text
yeah, they are all functions
Slide 55
Slide 55 text
yeah, they are all functions
@property , @staticmethod , @classmethod are all functions, in-built
ones. can be used as property() , staticmethod() and
classmethod .
try help on them
print(help(property))