Jamie Marshall
Jamie Marshall

Reputation: 2304

Python Set Parent to an Instance

Is there a way to just set a parent object to a particular instance? I have a utility that initializes a complex object for me and i'd like to have it init some objects for mocking. Example:

class ComplexObject:
   def __init__(arg1, arg2, arg3):
       #do some stuff
       return

class ComplexObject_Mock(ComplexObject):
    def __init__():
        complexObject = ComplexObjectFactory.NewComplexObject()
        return super() = complexObject

Now I know the above doesn't work, because of the last line. Usually I create the instance of the parent class by using super().__init(arg1, arg2, arg3), but instead of that i'd like to just set the instance to something initialized by the factory.

Upvotes: 1

Views: 1349

Answers (1)

abarnert
abarnert

Reputation: 365707

First, there are multiple problems with this line:

return super() = complexObject
  • You can't do an assignment (or any other statement) inside a return, only an expression.
  • You can't do an assignment to the result of a function call, only to a nameable target—a variable, an attribute of an object, an index in a list, etc.
  • If you could do an assignment to the result of a function call, that wouldn't do anything useful. You'd just be rebinding some invisible temporary name to a different value.
  • Even if you could, super() returns a special magic proxy object, so forcing it to return some other object that doesn't know how to act like a super would just break everything.
  • Finally, what super() returns is a proxy to self. If you somehow made it into a proxy into a completely unrelated object, then every method you called on super() would end up accessing and mutating the attributes of that completely unrelated object, which would have no effect on self.

Also, __init__ is a normal method, that requires a self or it can't be called.

Meanwhile, if you're trying to change the way an object is created, not just the way it's initialized, you have to use __new__, not __init__.

Finally, the whole point of mocking is that you don't have to create a ComplexObject; you're creating something that acts like one without being one, so the whole thing doesn't make much sense in the first place.

This is kind of a wild guess, but I think what you really want here is a proxy object that owns a ComplexObject, and also fakes being one, delegating some calls and handling others on its own. In other words:

class ComplexObject_Mock(ComplexObject):
    def __init__(self):
        self.complexObject = ComplexObjectFactory.NewComplexObject()
    def method_to_delegate(self, arg):
        # instead of return super().method_to_delegate(arg)
        return self.complexObject.method_to_delegate(arg)
    def method_to_steal(self, arg):
        # don't call self.complexObject.method_to_steal
        # just as you wouldn't have called super().method_to_steal
    def method_to_hook(self, arg):
        arg = self._preprocess(arg)
        # instead of result = super().method_to_hook(arg)
        result = self.complexObject.method_to_hook(arg)
        return self._postprocess(result)

Upvotes: 1

Related Questions