Question

Say I have a function or method that does something repetitive, like checking a value, before performing every operation it does, like so:

def myfunc():
    if mybool:
        do_operation_1()
    else:
        return

    if mybool:
        do_operation_2()
    else:
        return

    ...

These checks get repetitive, and end up wasting a lot of time and keyboard springs, especially when they are needed very often.

If you have control over the operation functions, like, do_operation_N you can decorate the functions with something that checks the boolean.

But what if you don't have control over the individual do_operation_N operations? If, for each line in a function or method, I want the same check to be performed, is there some way to "insert" it without explicitly writing it in on each operation line? For example, is there some decorator magic by which I could do the following?

def magic_decorator(to_decorate):
    def check(*args, **kwargs):
        for call in to_decorate: #magic
            if mybool:
                to_decorate.do_call(call) #magic
            else:
                return #or break, raise an exception, etc
    return check

@magic_decorator
def myfunc():
    do_operation_1()
    do_operation_2()
    ...

If there is a way to achieve this, I don't care if it uses decorators or not; I just want some way to say "for every line in function/method X, do Y first".

The "magic" example of a do_call method above is shorthand for what I'm after, but it would encounter serious problems with out-of-order execution of individual lines (for example, if a function's first line was a variable assignment, and its second was a use of that variable, executing them out of order would cause problems).

To be clear: the ability to externally control the line-by-line order of a function's execution is not what I'm trying to achieve: ideally, I'd just implement something that, in the natural execution order, would perform an operation each time myfunc does something. If "does something" ends up being limited to "calls a function or method" (excluding assignments, if checks, etc), that is fine.

Was it helpful?

Solution

Store your operations in a sequence, then use a loop:

ops = (do_operation_1, do_operation_2, do_operation_3)

for op in ops:
    if mybool:
        op()
    else:
        return

OTHER TIPS

Essentially, you can extract the file and line number from the decorated function, go re-read the function, compile it to an AST, insert nodes in the AST, and then compile the AST and use that as the function.

This method can be used for very long functions, which is a problem if you are using the approach above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top