动态地将方法附加到使用swig生成的现有Python对象? [英] Dynamically attaching a method to an existing Python object generated with swig?

查看:293
本文介绍了动态地将方法附加到使用swig生成的现有Python对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是Python类,我没有对其声明的写访问权限。
如何在不修改类声明的情况下将自定义方法(例如 __ str __ )附加到从该类创建的对象中? / p>

编辑:
谢谢您的所有答案。我试过他们,但他们没有解决我的问题。这里是一个最小的例子,我希望将澄清的问题。我使用swig包装一个C ++类,目的是重写由swig模块返回的一个对象 __ str __ 函数。我使用cmake建立示例:



test.py

  import example 

ex = example.generate_example(2)

def prnt(self):
return str(self.x)

#我们如何用prnt替换对象ex的__str__函数?
print ex
print prnt(ex)

example.hpp

  struct example 
{
int x;
};

示例generate_example(int x);

example.cpp

  #includeexample.hpp
#include< iostream>

示例generate_example(int x)
{
示例ex;
ex.x = x;
return ex;
}

int main()
{
示例ex = generate_example(2);
std :: cout<< ex.x<< \\\
;
return 1;
}

example.i

 %模块示例

%{
#includeexample.hpp
%}

%includeexample.hpp

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 .i属性CPLUSPLUS ON)
swig_add_module(示例python example.i示例)
swig_link_libraries(示例$ {PYTHON_LIBRARIES})

if(APPLE)
设置(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS $ {CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS} -flat_namespace)
endif(APPLE)

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

  cmake。 
make
python test.py

这将产生以下输出: / p>

 < example.example;代理< Swig Object of type'example *'at 0x10021cc40> > 
2

可以看到swig对象有自己的 str <强>功能,这是我想覆盖。

解决方案

如果你创建一个包装类,这将适用于任何其他类,这被称为包含和委派,它是继承的一个常见的替代方法:

  class SuperDuperWrapper(object):
def __init __(self,origobj):
self.myobj = origobj
def __str __(self):
returnSUPER DUPER+ str(self.myobj)
def __getattr __(self,attr):
return getattr(self.myobj,attr)

__ getattr __ 方法将您的SuperDuperWrapper对象上的所有未定义的属性请求委托给包含的myobj对象。事实上,给定Python的动态类型,你可以使用这个类来超级包装任何东西:

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

i = 100
sdi = SuperDuperWrapper(i)
print sdi

列印:

  SUPER DUPER hey ho! 
SUPER DUPER 100

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

  print sds.split()
['hey','ho!']


I am working with a Python class, and I don't have write access to its declaration. How can I attach a custom method (such as __str__) to the objects created from that class without modifying the class declaration?

EDIT: Thank you for all your answers. I tried them all but they haven't resolved my problem. Here is a minimal example that I hope will clarify the issue. I am using swig to wrap a C++ class, and the purpose is to override the __str__ function of an object returned by the swig module. I use cmake to build the example:

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)

example.hpp

struct example
{
    int x;
};

example generate_example(int x);

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;
}

example.i

%module example

%{
#include "example.hpp"
%}

%include "example.hpp"

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)

To build and run test.py, copy all the files in a directory, and in that directory run

cmake .
make 
python test.py

This results in the following output:

<example.example; proxy of <Swig Object of type 'example *' at 0x10021cc40> >
2

As you can see the swig object has its own str function, and that is what I am trying to override.

解决方案

If you create a wrapper class, this will work with any other class, either built-in or not. This is called "containment and delegation", and it is a common alternative to inheritance:

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)

The __getattr__ method will delegate all undefined attribute requests on your SuperDuperWrapper object to the contained myobj object. In fact, given Python's dynamic typing, you could use this class to SuperDuper'ly wrap just about anything:

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

i = 100
sdi = SuperDuperWrapper(i)
print sdi

Prints:

SUPER DUPER hey ho!
SUPER DUPER 100

In your case, you would take the returned object from the function you cannot modify, and wrap it in your own SuperDuperWrapper, but you could still otherwise access it just as if it were the base object.

print sds.split()
['hey', 'ho!']

这篇关于动态地将方法附加到使用swig生成的现有Python对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆