如何解决扩展具有相同名称的 Python 类并返回子类实例
我有一些使用 SWIG 自动生成的 Python 类,我想扩展它们。
问题是,这些类除了 __init__
之外还有另一个方法,称为 create
,它返回一个类实例(它们是真正的 init)。
我想用新方法扩展这些类,但保留原始名称。
我尝试实现 __new__
方法,但它返回父类的一个实例
我明白为什么会发生这种情况,但我似乎无法在保留 create
方法的同时找到改变它的方法。
让我用我的当前实现尝试向您展示一个示例,以便解释:
文件 a:
class A:
def __init__(self,...):
pass
def create(self,...):
# do some stuff
return object_of_A
文件 b:
from a import A as AClass
class A(AClass):
def __init__(self,...):
pass
def __new__(cls,...):
# do some stuff
return super(A,cls).create(...)
def foo(self):
print('Hi')
想要的行为:
>>> from b import A
>>> a = A(...)
>>> a.foo()
>>> Hi
实际行为:
>>> from b import A
>>> a = A(...)
>>> a.foo()
>>> AttributeError: 'A' object has no attribute 'foo'
谢谢!
解决方法
这是一个简单的例子。我创建了一个简单的静态方法,用于在 C++ 中创建对象,并用 SWIG 包装它。之后,我扩展了同名的类以稍微改变方法。
example.h
class A {
public:
static int Create(A** obj);
A() = default;
~A() = default;
int test();
};
example.cpp
#include "example.h"
int A::test() {
return 5;
}
int A::Create(A** obj) {
*obj = new A();
return 0;
}
example.i
%module example
%{
#include "example.h"
%}
%typemap(in,numinputs=0) A **obj (A *temp) {
$1 = &temp;
}
%typemap(argout) A ** {
PyObject* temp = NULL;
if (!PyList_Check($result)) {
temp = $result;
$result = PyList_New(1);
PyList_SetItem($result,temp);
}
// Create shadow object (do not use SWIG_POINTER_NEW)
temp = SWIG_NewPointerObj(SWIG_as_voidptr(*$1),$descriptor(A*),SWIG_POINTER_OWN | 0);
PyList_Append($result,temp);
Py_DECREF(temp);
}
%include "example.h"
setup.py
#!/usr/bin/env python
from distutils.core import setup,Extension
setup(name="example",py_modules=['example'],ext_modules=[Extension("_example",["example.i","example.cpp"],swig_opts=['-c++'],extra_compile_args=['--std=c++11']
)]
)
扩展.py
from example import A as parentA
class A(parentA):
def __init__(self):
super(A,self).__init__()
def SmartMethod(self):
return 2
@staticmethod
def Create():
retval,obj = parentA.Create()
obj.__class__ = A
return obj
extension.py
中定义的新类继承了原始类(如果有)的所有功能,这里是稍微更改 Create 方法的示例。
更改 __class__
属性的技巧将新对象转换为后代,因此可以调用 SmartMethod
。如果向后代添加其他成员,则必须在重载的 Create
方法中添加这些成员。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。