Skip to content

Instantly share code, notes, and snippets.

@jimathyp
Last active August 25, 2022 23:41
Show Gist options
  • Select an option

  • Save jimathyp/6a8cac8e2fc7fa761ab0292eeccd187d to your computer and use it in GitHub Desktop.

Select an option

Save jimathyp/6a8cac8e2fc7fa761ab0292eeccd187d to your computer and use it in GitHub Desktop.
notes for teaching decorators

Python decorators

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")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment