5.4. Decorator Function with Mth¶
5.4.1. Rationale¶
mydecorator
is a decorator namemethod
is a method nameself
is an instanceargs
arbitrary number of positional argumentskwargs
arbitrary number of keyword arguments
- Syntax:
class MyClass: @mydecorator def mymethod(self, *args, **kwargs): ... obj = MyClass() obj.mymethod()
- Is equivalent to:
class MyClass: def mymethod(self, *args, **kwargs): ... obj = MyClass() obj.mymethod = mydecorator(obj.mymethod)
5.4.2. Syntax¶
mydecorator
is a decorator namemymethod
is a method nameself
is an instanceargs
arbitrary number of positional argumentskwargs
arbitrary number of keyword arguments
Definition:
def mydecorator(method):
def wrapper(self, *args, **kwargs):
return method(self, *args, **kwargs)
return wrapper
Decoration:
class MyClass:
@mydecorator
def mymethod(self):
...
Usage:
my = MyClass()
my.mymethod()
5.4.3. Example¶
def run(method):
def wrapper(self, *args, **kwargs):
return method(self, *args, **kwargs)
return wrapper
class Astronaut:
@run
def hello(self, name):
return f'My name... {name}'
astro = Astronaut()
astro.hello('José Jiménez')
# 'My name... José Jiménez'
5.4.4. Use Cases¶
def if_allowed(method):
def wrapper(self, *args, **kwargs):
if self._is_allowed:
return method(self, *args, **kwargs)
else:
print('Sorry, Permission Denied')
return wrapper
class MyClass:
def __init__(self):
self._is_allowed = True
@if_allowed
def do_something(self):
print('Doing...')
@if_allowed
def do_something_else(self):
print('Doing something else...')
my = MyClass()
my.do_something() # Doing...
my.do_something_else() # Doing something else...
my._is_allowed = False
my.do_something() # Sorry, you cannot do anything
my.do_something_else() # Sorry, you cannot do anything
def paragraph(method):
def wrapper(self, *args, **kwargs):
result = method(self, *args, **kwargs)
return f'<p>{result}</p>'
return wrapper
class HTMLReport:
@paragraph
def first(self, *args, **kwargs):
return 'First'
@paragraph
def second(self, *args, **kwargs):
return 'Second'
x = HTMLReport()
x.first()
# '<p>First</p>'
x.second()
# '<p>Second</p>'
5.4.5. Assignments¶
"""
* Assignment: Decorator Method Syntax
* Complexity: easy
* Lines of code: 5 lines
* Time: 5 min
English:
1. Create method decorator `mydecorator`
2. Decorator should have `wrapper` with `self`, `*args` and `**kwargs` parameters
3. Wrapper should call original method with it's original parameters,
and return its value
4. Decorator should return `wrapper` method
5. Run doctests - all must succeed
Polish:
1. Stwórz dekorator metod `mydecorator`
2. Dekorator powinien mieć `wrapper` z parametrami `*args` i `**kwargs`
3. Wrapper powinien wywoływać oryginalną funkcję z jej oryginalnymi
parametrami i zwracać jej wartość
4. Decorator powinien zwracać metodę `wrapper`
5. Uruchom doctesty - wszystkie muszą się powieść
Tests:
>>> from inspect import isfunction
>>> assert isfunction(mydecorator)
>>> assert isfunction(mydecorator(lambda: None))
>>> class MyClass:
... @mydecorator
... def echo(text):
... return text
>>> my = MyClass()
>>> my.echo('hello')
'hello'
"""
"""
* Assignment: Decorator Method Alive
* Complexity: easy
* Lines of code: 5 lines
* Time: 13 min
English:
1. Use data from "Given" section (see below)
2. Create `if_alive` method decorator
3. Decorator will allow running `make_damage` method
only if `current_health` is greater than 0
4. Run doctests - all must succeed
Polish:
1. Użyj kodu z sekcji "Given" (patrz poniżej)
2. Stwórz dekorator metody `if_alive`
3. Dekorator pozwoli na wykonanie metody `make_damage`,
tylko gdy `current_health` jest większe niż 0
4. Uruchom doctesty - wszystkie muszą się powieść
Tests:
>>> class Hero:
... def __init__(self, name):
... self.name = name
... self.current_health = 100
...
... @if_alive
... def make_damage(self):
... return 10
>>> hero = Hero('Jan Twardowski')
>>> hero.make_damage()
10
>>> hero.current_health = -10
>>> hero.make_damage()
Traceback (most recent call last):
RuntimeError: Hero is dead and cannot make damage
"""
# Given
def if_alive(method):
def wrapper(hero, *args, **kwargs):
return method(hero, *args, **kwargs)
return wrapper