Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 一次重写所有类方法以执行相同的操作_Python_Python 3.x - Fatal编程技术网

Python 一次重写所有类方法以执行相同的操作

Python 一次重写所有类方法以执行相同的操作,python,python-3.x,Python,Python 3.x,我使用的是一个第三方API,它提供了一个Python包装类,其中包含约50个方法,这些方法除了接受一组任意参数外,什么都不做。然后,我要创建自己的类并重写这些方法中的每一个,以实现我真正想要的。我的问题是: 有很多方法需要重写,如果它们更改API,我必须使我的类与它们的类完全匹配:维护很糟糕 我使用多处理,希望将所有数据打包到MSG中,将它们放入队列中,并在另一个进程中处理结果,因此我不希望将数据处理逻辑放入此类中 他们班级的精简版: class TheirWrapper: def

我使用的是一个第三方API,它提供了一个Python包装类,其中包含约50个方法,这些方法除了接受一组任意参数外,什么都不做。然后,我要创建自己的类并重写这些方法中的每一个,以实现我真正想要的。我的问题是:

  • 有很多方法需要重写,如果它们更改API,我必须使我的类与它们的类完全匹配:维护很糟糕
  • 我使用多处理,希望将所有数据打包到MSG中,将它们放入队列中,并在另一个进程中处理结果,因此我不希望将数据处理逻辑放入此类中
他们班级的精简版:

class TheirWrapper:
    def __init__(self):
        pass
    def func1(self, a, b, c):
        pass
    def func2(self, d, e, f):
        pass
    ... and ~50 more
以及我工作的精简版本:

class MyWrapper:
    def addToQueue(self, localvars):
        # adds calling function name and localvars to queue (after removing self from localvars)
    def func1(self, a, b, c):
        self.addToQueue(locals())
    def func1=2(self, d, e, f):
        self.addToQueue(locals())
    ... and ~50 more

考虑到我在每个被重写的方法(
self.addToQueue(locals())
)中做的事情完全相同,我希望能够一次重写它们的所有方法(除了
\uuu init\uuu
)来做这一件事。这样做可能吗?

这里有一种可能的方法,使用
dir()检查
说唱者的内容:

导入检查
为他们的说唱者分类:
定义初始化(自):
通过
def func1(自身、a、b、c):
通过
def func2(自身、d、e、f):
通过
类MyWrapper:
def addToQueue(self,localvars):
#您的实现
打印(localvars)
###您可以将这个块组织成decorator或元类,使其更通用
def添加函数(函数名称):
def添加(自身、*args、**kwargs):
signature=inspect.signature(getattr(他们的说话者,函数名))
bind=signature.bind(self,*args,**kwargs)
arguments=dict(bind.arguments)
参数['func_name']=func_name
self.addToQueue(参数)
返回添加
对于目录中的名称(他们的说话者):
如果不是name.startswith(“”“”):
setattr(MyWrapper,name,add_func(name))
###
w=MyWrapper()
w、 函数1(1,2,3)
#打印{'self':,'a':1,'b':2,'c':3,'func_name':'func1'}


非常好的解决方案,我学到了一些东西。不幸的是,
addToQueue
需要调用函数的名称;它当前使用的是
sys.\u getframe(1).f\u code.co\u name
,但现在返回的是
add
,而不是实际重写的函数名。难道不能保留原来的名字吗?@fantabolous请查看更新后的答案。现在您已经在传递的
localvars
字典中找到了
'func_name':'func1'
。谢谢,这样就可以获得函数名了。我现在意识到args/kwargs对我也不起作用:所有函数的参数都在args中的值列表中,没有参数名,没有参数名,我无法处理它们。e、 g.对于func1,我只得到args=[1,2,3],而不是a=1、b=2和c=3。@fantabolous又更新了一次。现在你有了一本以参数名为键的字典。算上我,我印象深刻。它工作得很好。非常感谢你。
import inspect


class TheirWrapper:
    def __init__(self):
        pass
    def func1(self, a, b, c):
        pass
    def func2(self, d, e, f):
        pass


class MyWrapper:
    def addToQueue(self, localvars):
        # your implementation
        print(localvars)


### You can orginize this block into decorator or metaclass and make more general
def add_func(func_name):
    def add(self, *args, **kwargs):
        signature = inspect.signature(getattr(TheirWrapper, func_name))
        bind = signature.bind(self, *args, **kwargs)
        arguments = dict(bind.arguments)
        arguments['func_name'] = func_name
        self.addToQueue(arguments)
    return add


for name in dir(TheirWrapper):
    if not name.startswith('__'):
        setattr(MyWrapper, name, add_func(name))
###

w = MyWrapper()
w.func1(1, 2, 3)
# prints {'self': <__main__.MyWrapper object at 0x00000000030262E8>, 'a': 1, 'b': 2, 'c': 3, 'func_name': 'func1'}