调用与升压蟒蛇的输入参数变量数量Python函数
问题描述:
是否有可能调用具有从内部的boost :: python的可变数量的输入参数一个Python函数:调用与升压蟒蛇的输入参数变量数量Python函数
在Python中,我定义一个函数
def py_fn1(a):
return 2 * a
def py_fn2(a, b):
return a+b
def call_fn_py(fn, *args):
return fn(*args)
a = call_fn_py(py_fn1, 15) # returns 30
b = call_fn_py(py_fn2, 10, 11) # returns 21
根据评论给出结果。我想用boost python在C++中实现call_fn(fn,* args)。到目前为止,我有:
using namespace boost::python;
object call_fn(object fn, tuple arg_in)
{
return fn(arg_in);
}
BOOST_PYTHON_MODULE(python_addins)
{
using namespace boost::python;
def("call_fn", &call_fn);
}
但随后做这样的事情:
import python_addins
d = python_addins.call_fn(py_fn1, (5,)) # returns (5,5)
这是不是一上午后。我如何编写call_fn来表现得像call_fn_py?
谢谢,马克
答
它可以调用一个python函数的参数个数可变。有两种方法:
- 通过创建一组
call_fn
函数模仿可变数量的自变量。 - 利用python将多个对象打包并解包为元组的能力。
第一种方法是为通用的C++编程相当普遍。它需要创建一组根据参数数量而变化的重载函数:call_fn(fn)
,call_fn(fn, A1)
,call_fn(fn, A1, ...An)
。使用C++ 11可变参数模板函数可以减少样板代码的数量。但是,在定义包装时,必须指定模板函数的精确类型。因此,这种方法将基于包含什么样的模板实例来限制参数的数量。
#include <boost/python.hpp>
using boost::python;
object call_fn1(object fn, object a1)
{
return fn(a1);
}
object call_fn2(object fn, object a1, object a2)
{
return fn(a1, a2);
}
object call_fn3(object fn, object a1, object a2, object a3)
{
return fn(a1, a2, a3);
}
BOOST_PYTHON_MODULE(example)
{
def("call_fn", &call_fn1);
def("call_fn", &call_fn2);
def("call_fn", &call_fn3);
}
这里是一个演示:
>>> def py_fn1(a): return 2 * a
...
>>> def py_fn2(a, b): return a + b
...
>>> def call_fn_py(fn, *args):
... from example import call_fn
... return call_fn(fn, *args)
...
>>> call_fn_py(py_fn1, 15)
30
>>> call_fn_py(py_fn2, 10, 11)
21
第二种方法利用元组。它需要调用者将参数打包到一个元组中,并调用函数来解压参数。但是,由于在python中执行元组打包和解压缩更容易,因此example.call_fn
可以用python打补丁,以便函数参数用辅助函数进行装饰,该辅助函数可以在委派前解开参数。
在C++中,创建一个call_fn
函数,该函数接受单个boost::python::tuple
参数。现在
#include <boost/python.hpp>
using namespace boost::python;
object call_fn(object fn, tuple args)
{
return fn(args);
}
BOOST_PYTHON_MODULE(example)
{
def("call_fn", &call_fn);
}
,创建example_ext.py
将修补example.call_fn
:
import example
def patch_call_fn():
# Store handle to unpatched call_fn.
original = example.call_fn
# Helper function to create a closure that unpacks arguments
# before delegating to the user function.
def unpack_args(fn):
def wrapper(args):
return fn(*args)
return wrapper
# The patched function that will wrap the user function.
def call_fn(fn, *args):
return original(unpack_args(fn), args)
return call_fn
# Patch example.
example.call_fn = call_fn = patch_call_fn()
同样的演示可以使用,唯一需要改变的是example_ext
需要进口,而不是example
。
>>> def py_fn1(a): return 2 * a
...
>>> def py_fn2(a, b): return a + b
...
>>> def call_fn_py(fn, *args):
... from example_ext import call_fn
... return call_fn(fn, *args)
...
>>> call_fn_py(py_fn1, 15)
30
>>> call_fn_py(py_fn2, 10, 11)
21