python: 将实例方法及其参数传递给函数执行

python: passing an Instance Method and its argument to function for execution

我知道如何将函数作为参数传递,然后再使用该函数。但是我不知道如何用一种方法来做到这一点。我想为用户提供一个“API”,允许他们配置自定义功能。

作为一个(非)工作示例,假设我希望用户能够提供一些通用的 pandas 功能:

import pandas as pd

# user-supplied data
right = pd.DataFrame({'right_a':[1,2],
                      'right_b':[3,4]})

# user-supplied function & arguments 
myfun = pd.DataFrame.merge
args = {'right':right,
        'right_on':'right_a',
        'how':'inner'
        } 

user_configs = {'func': myfun,
                'args':args}

def exec_func(exec_dict):
    # some data that only the function knows:
    left = pd.DataFrame({'left_a':[1,2],'left_b':['foo','bar']})
    
    # some args that only the function knows
    exec_dict['args']['left_on'] = 'left_a'
    
    # apply the function
    #result = left.merge(**exec_dict['args'])  # desired result
    result = left.exec_dict['func'](**exec_dict['args']) # generalized but not working code
    return result

exec_func(user_configs)
    

上面的代码导致

AttributeError: 'DataFrame' object has no attribute 'exec_dict'

出于显而易见的原因。我怎样才能实现所需的行为,允许用户提供不同的功能?

所以我稍微简化了你的问题并省略了pandas。通过名称调用实例方法的方法是通过 getattribute 方法:

class MethodProvider (object):
    
    def __init__(self):
        pass
    
    def method1(self, foo):
        print('Method1 was called with arguments %s'%foo)
    
    def method2(self, baz):
        print('Method2 was called with argument %s'%baz)
        
def exec_method(obj, meth, kwargs):
    func = obj.__getattribute__(meth)
    func(**kwargs)

# Test construction 
mp = MethodProvider()

exec_method(
    mp,
    'method1',
    {'foo': 'bar'}
)

exec_method(
    mp,
    'method2',
    {'baz': 'buzz'}
)

方法,笼统地说,函数接收实例作为第一个参数exec_dict['func']已经是方法了,不需要在left上查找。只需将 left 作为第一个参数传递。

   #        |method/function|| called with...          |
   result = exec_dict['func'](left, **exec_dict['args'])
   #                         | instance
   #                                | further arguments

此代码适用于任何将数据帧 left 作为其第一个参数的可调用对象,而不仅仅是数据帧方法。


funcargs 不是期望包裹在字典中,而是 exec_func 可以直接接收它们。 left_on也可以直接传

def exec_func(func, **args):
    left = pd.DataFrame({'left_a':[1,2],'left_b':['foo','bar']})
    # apply the function
    result = func(left, left_on='left_a', **args)
    return result

exec_func(**user_configs)

注意习惯上使用args for positional and kwargs for keyword arguments/parameters,即def exec_func(func, *args, **kwargs): ....