动态地附接至与痛饮生成的现有的Python对象的方法?(Dynamically attaching

2019-07-04 23:43发布

我有一个Python类的工作,我没有它的声明写访问。 我怎么能把一个自定义的方法(如__str__ ),以不修改类声明该类创建的对象?

编辑:谢谢所有的答案。 我想他们所有,但他们并没有解决我的问题。 这里是我希望能澄清这个问题小例子。 我使用痛饮包装一个C ++类,其目的是覆盖__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)

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)

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

cmake .
make 
python test.py

这将导致以下的输出:

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

正如你可以看到痛饮对象都有自己STR功能,而这正是我试图重写。

Answer 1:

如果你创建一个包装类,这与其他任何类,无论是内置或无法正常工作。 这就是所谓的“遏制和代表团”,这是继承一个共同的选择:

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包裹任何内容:

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


Answer 2:

>>> class C(object):
...     pass
... 
>>> def spam(self):
...     return 'spam'
... 
>>> C.__str__ = spam
>>> print C()
spam

它不会对它们使用类工作__slots__



Answer 3:

创建一个子类。 例:

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


Answer 4:

这是我的回答另一个问题 :

import types
class someclass(object):
    val = "Value"
    def some_method(self):
        print self.val

def some_method_upper(self):
    print self.val.upper()

obj = someclass()
obj.some_method()

obj.some_method = types.MethodType(some_method_upper, obj)
obj.some_method()


Answer 5:

请注意,使用Alex的子类的想法,你可以帮助自己多一点使用“ from ...... import ...... as ”:

from datetime import datetime as datetime_original

class datetime(datetime_original):
   def __str__(self):
      return 'spam'

所以现在的类有标准的名称,但不同的行为。

>>> print datetime.now()
    'spam'

当然,这可能是危险的......



文章来源: Dynamically attaching a method to an existing Python object generated with swig?