我要做的是在另一个模块周围编写一个包装器,以便我可以转换传递给另一个模块的方法的参数。这是相当令人困惑的,所以这是一个例子:
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__
,但我不完全确定如何将它用于此应用程序。
答案 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')