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

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

问题描述

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

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?

感谢您的所有回答.我尝试了所有这些,但它们都没有解决我的问题.这是一个最小的例子,我希望能澄清这个问题.我使用swig来包装一个C++类,目的是覆盖swig模块返回的对象__str__函数.我使用 cmake 来构建示例:

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 << "
";
    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)

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

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

cmake .
make 
python test.py

结果如下:

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

正如你所看到的,swig 对象有它自己的 str 函数,这就是我想要覆盖的.

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)

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

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

打印:

SUPER DUPER hey ho!
SUPER DUPER 100

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

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天全站免登陆