Session 6 - Functions & Decorators
In Python, decorators allow you to add new functionality to your code by decorating functions or classes with additional code. This can make your code more modular and easier to maintain, as you can separate different concerns into separate decorators.
The boilerplate syntax of a decorator is like this:
1def decorator(func):
2 def wrapper_decorator(*args, **kwargs):
3 # Do something before
4 value = func(*args, **kwargs)
5 # Do something after
6 return value
7
8 return wrapper_decorator
And if you want to use it you will do like so:
1@decorator
2def greet(name):
3 return 'Hello ' + name
Learning goals
By reading the texts in the materials section, doing the 3 exercises, and follow the teachings, you will be able to explain what a decorator is, when to use it, and how the inner parts of a decorator function is made up, and you will be able to create your own, and use others already made decorators.
After this week you will know about and be able to use and explain:
First class functions
Inner functions
- Decorator functions
explain how a decorator function works
understand what the return values and return types are of the different functions used in a decorator
understand why we reuse the variable names in the scope.
Materials
Exercises
Warm up exercises
Think about the each of the following functions and determain what are the:
return value
return type
parameter type
parameter value
example1
1def add():
2 pass
example2
1def add():
2 print('Hello')
example3
1def add(num):
2 return num + num
example4
1def add(*args):
2 return sum(args)
example5
1def add(*args):
2 if all(type(element) == type(args[0]) for element in args):
3 return sum(args)
4 return None
Small Exercises
With this function as a starting point
1def add(*args):
2 return sum(args)
Write a decorator that writes to a log file the time stamp of each time this function is called.
Change the log decorator to also printing the values of the argument together with the timestamp.
Print the result of the decorated function to the log file also.
Create a new function and call it printer(text) that takes a text as parameter and returns the text. Decorate it with your logfunction. Does it work?
Ex1: Time it!
Next week we will work with generators, generator expressions and list comprehensions. These topics has a lot to do with program efficiency.
For this we will be measuring our code in diffenrent ways and especialy we will ‘time it’ and ‘messure memmory usage’.
If you want to messure how much time it takes to execute a piece of code you could do the followin:
1import time
2
3start = time.time()
4// do some stuff you want to meassure here
5end = time.time()
6print(end - start)
Instead of writing this every time you need to time something, you could write a docorator function that does the job for you.
Task:
Your job is, to write a decorator function that can time any piece of code.
You can read about time by starting your interpretor and write:
> import time
> help(time)
Ex3: Slow down code
The code below counts down from n -> 0. So calling countdown(5) prints: 5 4 3 2 1 Liftoff!
1def countdown(n):
2 if not n: # 0 is false, not false is true
3 return n
4 else:
5 print(n, end=' ')
6 return countdown(n-1) # call the same function with n as one less
(The function is a recursive function, which you might or might not have worked with before.)
Task:
Create a decorator function that slows down your code by 1 second for each step. Call this function slowdown()
For this you should use the ‘time’ module.
When you got the ‘slowdown code’ working on this recursive function, try to create a more (for you) normal function that does the countdown using a loop, and see what happens if you decorate that function with you slowdown() function.
Ex4: Decorating Game Characters
Background In the world of computer games, every character has a unique skill or ability that makes them special. For example, a character might have the ability to shoot accurately, move stealthily, or hack into computers.
We’re going to use Python decorators to add unique skills or abilities to game characters.
Task Create a Python decorator that adds a unique skill or ability to a game character. The decorator should be reusable, so that we can add multiple skills or abilities to a character.
Example Here’s an example of how the decorator might be used:
1@sharpshooter
2@stealthy
3def player():
4 return "I'm the player character"
5
6print(player())
The output of the code should be:
I'm the player character, the sharpshooter and stealthy character.
Steps
Create a decorator function that takes a function as an argument and returns a new function that adds a unique skill or ability to the character’s description.
Add the decorator to the player() function to add the “sharpshooter” and “stealthy” abilities to the player character.
Test your code to make sure it works as expected.
Bonus
Create additional decorators for other skills or abilities that might be found in a computer game.
Add multiple skills or abilities to a single character by stacking multiple decorators.