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
作为其第一个参数的可调用对象,而不仅仅是数据帧方法。
func
和 args
不是期望包裹在字典中,而是 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): ...
.
我知道如何将函数作为参数传递,然后再使用该函数。但是我不知道如何用一种方法来做到这一点。我想为用户提供一个“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
作为其第一个参数的可调用对象,而不仅仅是数据帧方法。
func
和 args
不是期望包裹在字典中,而是 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): ...
.