Search code examples
pythonpython-c-api

is it possible to overwrite "self" to point to another object inside self.method in python?


class Wrapper(object):
    def __init__(self, o):
        # get wrapped object and do something with it
        self.o = o
    def fun(self, *args, **kwargs):
        self = self.o # here want to swap
        # or some low level C api like
        # some_assign(self, self.o)
        # so that it swaps id() mem addr to self.o
        return self.fun(*args, **kwargs) # and now it's class A

class A(object):
    def fun(self):
        return 'A.fun'

a = A()
w = Wrapper(a)
print(type(w)) # wrapper
print(w.fun()) # some operation after which I want to loose Wrapper
print(a is w) # this goes False and I'd like True :) 
             # so that this is the original A() object 

Is there any way to do this in Python?


Solution

  • Assigning to self inside a method simply rebinds the local variable self to the new object. Generally, an assignment to a bare name never changes any objects, it just rebinds the name on the left-hand side to point to the object on the right-hand side.

    So what you would need to do is modify the object self points to to match the object self.o points to. This is only possible if both A and Wrapper are new-style classes and none of them defines __slots__:

    self.__class__ = self.o.__class__
    self.__dict__ = self.o.__dict__
    

    This will work in CPython, but I'm not sure about the other Python implementation. And even in CPython, it's a terrible idea to do this.

    (Note that the is condition in the last line of your code will still be False, but I think this does what you intend.)