将方法动态附加到使用swig生成的现有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

我正在使用一个Python类,并且我没有对其声明的写访问权。 如何在不修改类声明的情况下,将自定义方法(如
\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!']