python 用于ExcelPython函数的Python装饰器。避免由Excel刷新机制导致的冗余Python函数调用。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 用于ExcelPython函数的Python装饰器。避免由Excel刷新机制导致的冗余Python函数调用。相关的知识,希望对你有一定的参考价值。

import pandas as pd
import wrapt


def _apply_function_to_named_arg(func, arg_name):
    @wrapt.decorator
    def wrapper(wrapped, instance, args, kwargs):
        # Get argument names
        code = wrapped.__code__
        names = code.co_varnames[:code.co_argcount]

        # Convert both args and kwargs to a kwargs-style dict called all_args
        all_args = kwargs.copy()  # copy keyword args
        for n, v in zip(names, args):  # append positional args
            all_args[n] = v

        # Apply the transformation defined by `func` to the named arg
        all_args[arg_name] = func(all_args[arg_name])

        # Call the wrapped function and return its output
        return wrapped(**all_args)
    return wrapper

def negate_var(arg_name):
    return _apply_function_to_named_arg(lambda x: -x, arg_name)

@negate_var("offset")
def foo(abc, offset=1):
    return abc + offset

# Monkey-patch
pd.Series.foo = foo

# Test if it works
s = pd.Series([1, 2, 3, 4, 5])

print('Input\n-----')
print(s)
print('\nOutput of method call\n---------------------')
print(s.foo(offset=3))
print('\nOutput of function call\n-----------------------')
print(foo(s, offset=3))
## General example functions
def decorator_with_args_and_kwargs(*dec_args,**dec_kwargs):
    def wrap(f):
        print("Wrapping function...")
        def wrapped_f(*args, **kwargs):
            print("Inside wrapped function")
            print("Decorator args:", dec_args)
            print("Function args:", args)
            print("Decorator kwargs:", dec_kwargs)
            print("Function kwargs:", kwargs)
            output = f(*args,**kwargs)
            print("After f(*args,**kwargs)")
            return output
        print("Done wrapping, returning wrapped function")
        return wrapped_f
    print("Returning wrapping function")
    return wrap

def decorator_replacing_named_arg(arg_name):
    def wrap(f):
        print("Wrapping function...")
        def wrapped_f(*args, **kwargs):
            print("Inside wrapped function")
            print("Function args:", args)
            print("Function kwargs:", kwargs)

            try: # check if variable name was specified as a keyword arg
                named_arg = kwargs[arg_name]

                # Apply any transformation to the named arg
                # BEGIN
                named_arg = 0
                # END

                kwargs[arg_name] = named_arg
            except KeyError: # find the position in which the named arg is expected
                try:
                    arg_pos = f.__code__.co_varnames.index(arg_name)
                    args = list(args)  # make args mutable
                    named_arg = args[arg_pos]  # assign the named arg to a variable

                    # Apply any transformation to the named arg
                    # BEGIN
                    named_arg = 0
                    # END

                    args[arg_pos] = named_arg  # insert it back in the arg list
                    args = tuple(args)  # convert args back to a tuple
                except ValueError:
                    pass
                except IndexError:
                    pass
            output = f(*args,**kwargs)
            print("After f(*args,**kwargs)")
            return output
        print("Done wrapping, returning wrapped function")
        return wrapped_f
    print("Returning wrapping function")
    return wrap

## Specific examples
def _apply_function_to_named_arg(f, arg_name):
    # Executed when decorating the function
    # called first, when intercept(arg_names) is executed
    # returns the actual decorator which, in the second step, will receive the function as the only argument
    def decorator(func):
        # Executed when decorating the function
        # called second, this is the actual decorator

        # Try to access the arguments which were originally passed to the function which are expected
        # to be in `func._names` if `func` was already decorated
        names = getattr(func,'_names',None)
        # If `func` was not decorated before, save the input arg names in variable names
        if names is None:
            code = func.__code__
            names = code.co_varnames[:code.co_argcount]
        @wraps(func)
        def decorated(*args,**kwargs):
            # Executed on every function call
            # Convert both args and kwargs to a kwargs-style dict called all_args
            all_args = kwargs.copy()
            for n,v in zip(names,args):
                all_args[n] = v

            # Apply the transformation defined by `f` to the named arg
            all_args[arg_name] = f(all_args[arg_name])

            # Once the arguments have been overwritten, call the function
            return func(**all_args)
        decorated._names = names  # store the attributes for subsequent decorations
        return decorated
    return decorator

def negate_var(arg_name):
    return _apply_function_to_named_arg(lambda x: -x, arg_name)

@negate_var('a')
@negate_var('b')
def foo(a,b=0):
    return a+b

foo(3,2)
def noblink(func):
    def inner(*args, **kwargs):
        first_call = not(hasattr(inner, 'args')) or not(hasattr(inner, 'kwargs'))
        if not(first_call):
            new_args = not(isequal(args,inner.args) and isequal(kwargs,inner.kwargs))
        if first_call or new_args:
            #Evaluate function
            output = func(*args, **kwargs)
            # Save input arguments and output
            inner.args = args
            inner.kwargs = kwargs
            inner.output = output      
        return inner.output
    def isequal(a, b, tol=0):
        return a == b
    return inner

以上是关于python 用于ExcelPython函数的Python装饰器。避免由Excel刷新机制导致的冗余Python函数调用。的主要内容,如果未能解决你的问题,请参考以下文章

ExcelPython靠边站,这才是实现报表自动化最快的方法

[py]python内存管理

在 Python 中解析 .c/.cpp/.py 源文件以获取包含的函数列表

如何使包模块中的函数立即可用于 Python3 中的根应用程序

python-sys模块

执行python文件不再依靠python函数