将方法动态附加到使用swig生成的现有Python对象?

dzh*_*lil 9 python methods class dynamic

我正在使用Python类,并且我没有对其声明的写入权限.如何__str__在不修改类声明的情况下将自定义方法(如)附加到从该类创建的对象中?

编辑:谢谢你的所有答案.我尝试了所有这些,但他们没有解决我的问题.这是一个最小的例子,我希望能澄清这个问题.我使用swig来包装C++类,目的是覆盖swig模块返回的对象__str__功能.我使用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)
Run Code Online (Sandbox Code Playgroud)

example.hpp

struct example
{
    int x;
};

example generate_example(int x);
Run Code Online (Sandbox Code Playgroud)

example.cpp

#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;
}
Run Code Online (Sandbox Code Playgroud)

example.i

%module example

%{
#include "example.hpp"
%}

%include "example.hpp"
Run Code Online (Sandbox Code Playgroud)

的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)
Run Code Online (Sandbox Code Playgroud)

要构建并运行test.py,请复制目录中的所有文件,并在该目录中运行

cmake .
make 
python test.py
Run Code Online (Sandbox Code Playgroud)

这导致以下输出:

<example.example; proxy of <Swig Object of type 'example *' at 0x10021cc40> >
2
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,Swig对象具有自己的str函数,这就是我想要覆盖的内容.

Pau*_*McG 21

如果您创建一个包装类,这将适用于任何其他类,无论是内置还是非内置.这称为"包含和委托",它是继承的常见替代方法:

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)
Run Code Online (Sandbox Code Playgroud)

__getattr__方法将SuperDuperWrapper对象上的所有未定义属性请求委托给包含的myobj对象.事实上,考虑到Python的动态类型,你可以使用这个类来SuperDuper'包装任何东西:

s = "hey ho!"
sds = SuperDuperWrapper(s)
print sds

i = 100
sdi = SuperDuperWrapper(i)
print sdi
Run Code Online (Sandbox Code Playgroud)

打印:

SUPER DUPER hey ho!
SUPER DUPER 100
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您将从无法修改的函数中获取返回的对象,并将其包装在您自己的SuperDuperWrapper中,但您仍然可以访问它,就像它是基础对象一样.

print sds.split()
['hey', 'ho!']
Run Code Online (Sandbox Code Playgroud)