Tags

,

Recently, came up with a good use case for decorators. even though lot of articles says how decorators work. it confuses as the decorator method returns the same method and prints some message.

The usecase i thought was, in my project, whats the top 10 functions, which have  been used extensively. so i can optimize it, clean the code. Also add default documentation for the the functions by taking its parameters.

@cool is used to decorate methods increment and decrement. decrement ‘ll have documentation of parameters also the user defined one.

@cool is equivalent to

 decorated_function = cool(increment)

In the following code, class Meta does the job of keeping track of method call, also adding the params as documentation, also keeping track of maximum argument value.

class Meta:
    method_counts = {}
    max_value = 0

    @staticmethod
    def called(f):
        Meta.method_counts[f.__name__] = Meta.method_counts.get(f.__name__, 0) + 1

    @classmethod
    def get_method_count(cls, f = None):
        return cls.method_counts.get(f)

    @classmethod
    def update_max_val(cls, f, *args):
        if args:
            cls.max_value = max(args[0], cls.max_value)

    @staticmethod
    def get_arguments_as_doc(f):
        doc = "This method is decorated!\nIt takes %d arguments [" % f.func_code.co_argcount
        doc += " , ".join(f.func_code.co_varnames) + "].\n"
        if f.__doc__:
            doc += "User Defined Doc: " + f.__doc__
        return doc

def cool(f):

    def decorated_function(*args):
        # print("You Are Using A Decorated function")
        Meta.called(f)
        Meta.update_max_val(f, args)
        return f(*args)

    decorated_function.__doc__ = Meta.get_arguments_as_doc(f)
    return decorated_function

@cool
def increment(num, inc_val=1):
    return num + inc_val

newly_decorated_function = cool(increment)

@cool
def decrement(num):
    """decrements a number by 1"""
    return num - 1;

increment(1)
increment(20)
increment(3)

print(increment.__doc__)
print(decrement.__doc__)

decrement(0)
decrement(2)

print(Meta.method_counts)

The output of the above script ‘ll be

This method is decorated!
It takes 2 arguments [num , inc_val].

This method is decorated!
It takes 1 arguments [num].
User Defined Doc: decrements a number by 1

{‘decrement’: 2, ‘increment’: 3}

 

I’ve used python2.7. func_code is not available in 3.5 version.

recent versions of python access func_code as method.__code__.co_varnames

Now you can think about what is @staticmethod, @classmethod is doing ?

References:

Advertisements