gpt4 book ai didi

c++ - 从 C++ 捕获 boost::python 包装类的实例属性的创建

转载 作者:搜寻专家 更新时间:2023-10-31 00:45:46 26 4
gpt4 key购买 nike

我正在用 boost::python 包装(很多)c++ 类。如果我在从 python 脚本分配属性名称时输入错误,python 会静默创建新的实例属性,这绝不是我缩进的。有没有办法捕获此类事件(并引发异常?)?

我在网上看到了一些关于这个主题的帖子,但似乎都没有给出明确的答案;我试图覆盖 __setattr__ & friends,但我没能成功;另外,我担心可能会影响性能。

干杯,瓦茨拉夫

最佳答案

__setattr__ 实际上是要走的路。如果您担心性能,我认为 python 仍然会在内部进行此调用,因此覆盖该函数应该不会再有任何成本。 __setattr__ 的问题在于,如果您试图将您的实现保留在您的 C++ 代码中,那么实现起来可能会很棘手。

这是一个 python 版本:

# MyClassBase defined in C++ library
class MyClass(object):
def __init__(self):
self.test1 = 'test1'
self.__initialized = True
def __setattr__(self, name, value):
if not self.__dict__.has_key('_MyClass__initialized') or self.__dict__.has_key(name):
object.__setattr__(self, name, value)
else:
raise AttributeError("Attribute %s does not exist." % name)

def main():
o = MyClass()
print o.test1
o.test1 = 'test1_set'
print o.test1
# This will throw
o.test2 = 'test2_set'

if __name__ == '__main__':
main()

这是一种使用元类来实现的方法。这种方法的优点是你只需要定义一次 __setattr__ 函数,然后你就可以使用你的注入(inject)器类定义每个类:

# create an injector metaclass to add functionality to
# our modules, you can reuse BoostPythonMetaclass for
# all boost::python-exported objects
BoostPythonMetaclass = MyClass.__class__
class injector(object):
class __metaclass__(BoostPythonMetaclass):
def __init__(self, name, bases, dict):
for b in bases:
if type(b) not in (self, type):
for k,v in dict.items():
setattr(b,k,v)
setattr(b, '__initialized', True)
return type.__init__(self, name, bases, dict)

def __setattr__(self, name, value):
if not self.__dict__.has_key('_MyClass__initialized') or self.__dict__.has_key(name):
object.__setattr__(self, name, value)
else:
raise AttributeError("Attribute %s does not exist." % name)

# Use the injector to add our functionality
class MyClass(injector, MyClass):
pass

如果你想在 C++ 中做同样的事情,那就有点棘手了:

using namespace boost::python;

static void SetAttr(object self, str name, object value)
{
dict d = getattr(self, "__dict__");
if(d.has_key(name)) {
setattr(self, name, value);
} else {
std::stringstream ss;
ss << "Method" << extract<std::string>(name) << "does not exist.";
PyErr_SetString(PyExc_AttributeError, ss.str().c_str());
throw error_already_set();
}
}

BOOST_PYTHON_MODULE(mymodule)
{
class_<MyClass>("MyClass")
.def("__setattr__", &SetAttr);
}

关于c++ - 从 C++ 捕获 boost::python 包装类的实例属性的创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6120490/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com