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!']