将方法动态附加到使用swig生成的现有Python对象?
我正在使用一个Python类,并且我没有对其声明的写访问权。 如何在不修改类声明的情况下,将自定义方法(如将方法动态附加到使用swig生成的现有Python对象?,python,class,dynamic,methods,Python,Class,Dynamic,Methods,我正在使用一个Python类,并且我没有对其声明的写访问权。 如何在不修改类声明的情况下,将自定义方法(如\uuuu str\uuuu)附加到从该类创建的对象 编辑: 谢谢你的回答。我都试过了,但都没有解决我的问题。这里有一个最简单的例子,我希望能澄清这个问题。我使用SWIG来封装C++类,目的是重写Sigg模块返回的对象< /强>的我使用cmake构建示例: test.py import example ex = example.generate_example(2) def prnt(s
\uuuu str\uuuu
)附加到从该类创建的对象
编辑:
谢谢你的回答。我都试过了,但都没有解决我的问题。这里有一个最简单的例子,我希望能澄清这个问题。我使用SWIG来封装C++类,目的是重写Sigg模块返回的<强>对象< /强>的<代码>我使用cmake构建示例:
test.py
import example
ex = example.generate_example(2)
def prnt(self):
return str(self.x)
#How can I replace the __str__ function of object ex with prnt?
print ex
print prnt(ex)
示例.hpp
struct example
{
int x;
};
example generate_example(int x);
#include "example.hpp"
#include <iostream>
example generate_example(int x)
{
example ex;
ex.x = x;
return ex;
}
int main()
{
example ex = generate_example(2);
std::cout << ex.x << "\n";
return 1;
}
示例.cpp
struct example
{
int x;
};
example generate_example(int x);
#include "example.hpp"
#include <iostream>
example generate_example(int x)
{
example ex;
ex.x = x;
return ex;
}
int main()
{
example ex = generate_example(2);
std::cout << ex.x << "\n";
return 1;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
find_package(PythonLibs)
include_directories(${PYTHON_INCLUDE_PATH})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
swig_add_module(example python example.i example)
swig_link_libraries(example ${PYTHON_LIBRARIES})
if(APPLE)
set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "${CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -flat_namespace")
endif(APPLE)
要构建并运行test.py,请复制目录中的所有文件,然后在该目录中运行
cmake .
make
python test.py
这将产生以下输出:
<example.example; proxy of <Swig Object of type 'example *' at 0x10021cc40> >
2
2.
正如您所看到的,swig对象有自己的str函数,这就是我试图覆盖的
>>> class C(object):
... pass
...
>>> def spam(self):
... return 'spam'
...
>>> C.__str__ = spam
>>> print C()
spam
它在使用的类上不起作用。创建子类。例如:
>>> import datetime
>>> t = datetime.datetime.now()
>>> datetime.datetime.__str__ = lambda self: 'spam'
...
TypeError: cant set attributes of built-in/extension type 'datetime.datetime'
>>> t.__str__ = lambda self: 'spam'
...
AttributeError: 'datetime.datetime' object attribute '__str__' is read-only
>>> class mydate(datetime.datetime):
def __str__(self):
return 'spam'
>>> myt = mydate.now()
>>> print t
2009-09-05 13:11:34.600000
>>> print myt
spam
以下是我的回答:
请注意,使用Alex的子类思想,您可以使用“
from
…import
…as
”,为自己提供更多帮助:
因此,现在这个类有了标准名称,但有了不同的行为
>>> print datetime.now()
'spam'
当然,这可能是危险的…如果您创建一个包装类,它将与任何其他类一起工作,无论是否内置。这被称为“包容和委派”,是继承的常见替代方案:
class SuperDuperWrapper(object):
def __init__(self, origobj):
self.myobj = origobj
def __str__(self):
return "SUPER DUPER " + str(self.myobj)
def __getattr__(self,attr):
return getattr(self.myobj, attr)
\uuuu getattr\uuuu
方法将SuperDuperRapper对象上所有未定义的属性请求委托给包含的myobj对象。事实上,考虑到Python的动态类型,您可以使用这个类来SuperDupper’ly包装任何东西:
s = "hey ho!"
sds = SuperDuperWrapper(s)
print sds
i = 100
sdi = SuperDuperWrapper(i)
print sdi
印刷品:
SUPER DUPER hey ho!
SUPER DUPER 100
在您的情况下,您可以从无法修改的函数中获取返回的对象,并将其包装在您自己的SuperDuperRapper中,但您仍然可以像访问基本对象一样访问它
print sds.split()
['hey', 'ho!']
不幸的是,这在我的情况下不起作用。我试图覆盖的类是使用C++标题文件中的SWIG自动生成的。其他StAdExpLoad问题:谢谢亚历克斯的建议。的确,我可以轻松创建一个子类,但这对我帮助不大,因为我正在处理的对象是由一个我无法修改的函数返回的。在示例的上下文中,该对象的类型为datetime。我想重写它的
\uuuu str\uuuu
函数,因此为了使它有用,我需要一种方法将datetime对象强制转换为mydate。我在Python职业生涯的早期就使用了这种技术,为远程CORBA对象的代理编写了一个拦截器-客户端希望稍微增强一个特定的远程方法,但除此之外,其他一切都是一样的。最近才从C++切换过来,我很惊讶,写代码的代码少,而C++的应用却不太好。谢谢保罗!这正是我想要的。这种方法的问题是,生成的包装对象不可拾取,这有时是一个大问题+1。我很惊讶这对COM对象有效。我预计getattr
会失败。添加额外功能通常称为装饰器。
print sds.split()
['hey', 'ho!']