In Python a function is an object. It can be assigned to a variable, and calling a function is a separate action.
def some_func():
print("hi")
a = some_func
a()
>> "hi"A function can be returned from another:
def greeter(name):
""" get greeter function """
def greet(greeting):
""" greet person """
print(f"{greeting} {name}")
return greet
a = greeter("bob")
a("hi")
>> "hi bob"
# or combining
greeter("bob")("hi")
>> "hi bob"
``
# Decorators
def log(pre, post=None):
""" A wrapper decorator for logging entry/exit from methods.
The post function call is optional
Usage:
@log(entering, exiting)
def your_function(params):
...
@log(entering)
def your_function(params):
...
"""
def decorate(func):
""" The decorator applied to methods """
def call(*args, **kwargs):
""" Defines the wrapper """
pre(func)
# pre(func, *args)
result = func(*args, **kwargs)
post(func)
return result
return call
return decorate
# Decorator helper
def entering(func):
logger.debug(f'Entering {func.__name__}()')
# Decorator helper
def exiting(func):
logger.debug(f'Exiting {func.__name__}()')
@log(entering, exiting)
def some_funct()
# https://docs.python.org/3/library/functools.html
# https://stackoverflow.com/questions/308999/what-does-functools-wraps-do
# # decorator.py
# import functools
# def log_it(func):
# """ logger decorator"""
# @functools.wraps(func)
# def wrapper():
# """the wrapper"""
# print("before")
# func()
# print("after")
# return wrapper
# @log_it
# def some_function():
# """ some function to log """
# print()
# print("lots of processing")
# a = some_function
# print(a.__name__)
# print(a.__doc__)
# # some_function()
# # fn = log_it(some_function)()
# # some_function()
# # print("\nname:")
# # print(log_it.__name__)
# # print(some_function.__name__)
# # # functools.wraps only changes the name of the wrapped fn
# # def log_it(func):
# # def wrapper():
# # print("before")
# # func()
# # print("after")
# # return wrapper
# # @log_it
# # def some_function():
# # print("lots of processing")
# def logged(func):
# def with_logging(*args, **kwargs):
# print(func.__name__ + " was called")
# return func(*args, **kwargs)
# return with_logging
# @logged
# def f(x):
# """does some math"""
# return x + x * x
# # same as
# def f(x):
# """does some math"""
# return x + x * x
# f = logged(f)
# # however f.__name__ is now with_logging
def greeter(name):
""" get greeter function """
def greet(greeting):
""" greet person """
print(f"{greeting} {name}")
return greet
# greeter("bob")
# nothing happpened
# lets assign to val and check
# a = greeter("bob")
# print(a) # <function greeter.<locals>.greet at 0x7fdea133dd30>
# print(dir(a))
# print(type(a)) # <class 'function'>
# print(a.__doc__) # "greet person"
# print(a.__name__) # greet
# a("hi")
a = greeter("bob")("hi")