You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
4.2 KiB
126 lines
4.2 KiB
#https://www.datacamp.com/community/tutorials/decorators-python |
|
#A an example of how this can be actually useful is here: |
|
#https://www.codementor.io/sheena/advanced-use-python-decorators-class-function-du107nxsv |
|
|
|
def basicdeco(func): |
|
'''A basic wrapper that just adds things |
|
''' |
|
def wrapper(): |
|
print('Some code inside the wrapper runs here') |
|
return func() #function has to run unless you want to run something like ()() |
|
return wrapper |
|
|
|
def deco1(func): |
|
'''A wrapper that reads args and kwargs and does nothing with them |
|
#print('before wrapper 2: runs on definition') |
|
Note that placing things before the wrapper will case them to run before the |
|
decorated function call because they must run to wrap the function |
|
''' |
|
|
|
def wrapper(*args, **kwargs): |
|
print("This is decorated and took arguments (args, kwargs)") |
|
print(args, kwargs) |
|
print("but didn't pass them to the wrapped function") |
|
return func() |
|
return wrapper |
|
|
|
def deco2(func): |
|
'''A wrapper that reads args and kwargs and passes them to the function |
|
#print('before wrapper 2: runs on definition') |
|
Note that placing things before the wrapper will case them to run before the |
|
decorated function call because they must run to wrap the function |
|
|
|
Any positional arguments from the function are passed along with args. |
|
''' |
|
|
|
def wrapper(*args, **kwargs): |
|
print("This is decorated and took arguments (args, kwargs)") |
|
print(args, kwargs) |
|
print("but didn't pass them to the wrapped function") |
|
return func(*args, **kwargs) |
|
return wrapper |
|
|
|
def deco3(*args, **kwargs): |
|
'''This time it is the *decorator* that takes arguments, then passes them to |
|
the decorated function. You have to write a decorator *within* a decorator |
|
print('whatever') #would also run on wrap |
|
|
|
Remember that wrappers can access variables outside their scope, but not |
|
vice versa, so the args and kwargs can filter down. |
|
''' |
|
def insidedeco(func): |
|
print('These are the decorator args, kwargs:', args, kwargs)# prints on wrap |
|
def wrapper(*args1, **kwargs1): |
|
print("This is the decorated nested wrapper") |
|
print("Decorator variables", args, kwargs) |
|
print("Inner wrapper variables", args1, kwargs1) |
|
return func(*args1, **kwargs1) |
|
return wrapper |
|
return insidedeco |
|
|
|
def practical_example(func): |
|
'''A function counter wrapper''' |
|
def wrapper(*args, **kwargs): |
|
wrapper.count+=1 |
|
return func(*args, **kwargs) |
|
wrapper.count=0 #wrapper must be assigned first! That's why this is at the bottom. |
|
return wrapper |
|
|
|
@basicdeco |
|
def testme0(): |
|
print('@basic deco test function') |
|
print('Undecorated function takes no arguments') |
|
print(30*'_') |
|
|
|
@deco1 |
|
def testme1(): |
|
print('@deco1 test function') |
|
print(30*'_') |
|
|
|
@deco2 |
|
def testme2(positional): |
|
print('@deco 2 test function') |
|
print('positional variable', positional) |
|
print(30*'_') |
|
|
|
@deco3(deco3var="bollocks") |
|
def testme3(positional, *args, **kwargs): |
|
print('@deco3 test function') |
|
print('positional', positional) |
|
print('args, kwargs from decorated function:', args, kwargs) |
|
print(30*'_') |
|
|
|
@practical_example |
|
def countme(): |
|
'''see https://stackoverflow.com/questions/44968004/python-decorators-count-function-call |
|
for how the counting variable works |
|
''' |
|
print('I count for something:', countme.count) |
|
print(30*'_') |
|
|
|
@practical_example |
|
def second_count(): |
|
print('I also count as a separate object', second_count.count) |
|
print(30*'_') |
|
|
|
def wo_decorator_syntax(): |
|
'''Just to show how it works without syntax''' |
|
print('Manually wrapped') |
|
print(30*'_') |
|
|
|
|
|
if __name__ == '__main__': |
|
print('__main__ starts running here___') |
|
print(30*'_') |
|
#decorator without shorthand |
|
basicdeco(wo_decorator_syntax)() |
|
|
|
#decorators in action |
|
testme0() |
|
testme1(name='PassedVariable') |
|
testme2("myPositionalVariable") |
|
testme3("positionalVar", name=37) |
|
for i in range(10): |
|
countme() |
|
for i in range(5): |
|
second_count()
|
|
|