Python:如何拦截方法调用以更改函数参数?

时间:2017-07-06 16:15:36

标签: python

我要做的是在另一个模块周围编写一个包装器,以便我可以转换传递给另一个模块的方法的参数。这是相当令人困惑的,所以这是一个例子:

import somemodule

class Wrapper:
    def __init__(self):
        self.transforms = {}
        self.transforms["t"] = "test"

    # This next function is the one I want to exist
    # Please understand the lines below will not compile and are not real code
    def __intercept__(self, item, *args, **kwargs):
        if "t" in args:
            args[args.index("t")] = self.transforms["t"]
        return somemodule.item(*args, **kwargs)

目标是允许包装类的用户对底层模块进行简化调用,而无需重写模块中的所有函数。因此,在这种情况下,如果somemodule有一个名为print_uppercase的函数,则用户可以执行

w = Wrapper()
w.print_uppercase("t")

并获取输出

TEST

我相信答案在__getattr__,但我不完全确定如何将它用于此应用程序。

3 个答案:

答案 0 :(得分:1)

__getattr__结合动态定义函数应该有效:

# somemodule

def print_uppercase(x):
    print(x.upper())

现在:

from functools import wraps

import somemodule

class Wrapper:
    def __init__(self):
        self.transforms = {}
        self.transforms["t"] = "test"

    def __getattr__(self, attr):
        func = getattr(somemodule, attr)
        @wraps(func)
        def _wrapped(*args, **kwargs):
            if "t" in args:
                args = list(args)
                args[args.index("t")] = self.transforms["t"]
            return func(*args, **kwargs)
        return _wrapped


w = Wrapper()
w.print_uppercase('Hello')
w.print_uppercase('t')

输出:

HELLO
TEST

答案 1 :(得分:0)

我会通过调用拦截方法并输入所需的执行方法作为拦截参数来解决这个问题。然后,在拦截方法中,您可以搜索具有该名称的方法并执行它。

答案 2 :(得分:0)

由于您的Wrapper对象没有任何可变状态,因此在没有类的情况下实现起来会更容易。示例wrapper.py

def func1(*args, **kwargs):
  # do your transformations
  return somemodule.func1(*args, **kwargs)

然后称之为:

import wrapper as w
print w.func1('somearg')