0

Task: setattr(self, key, value) if hasattr(self, key) else setattr(otherobject, key, value) where otherobject is an attribute of self

The problem has two problems that I am unable to solve.

  1. setattr(self.baz, key, value) ends badly if __setattr__ is re-defined, because you cannot assign self.baz without calling __setattr__ which requires self.baz to be defined.

  2. I want the behavior of __getattr__ (called when the default attribute access fails) in my __setattr__ (called when an attribute assignment is attempted) where it is only called when hasattr(self, key) is False.

The below code is wrong; I expect that the solution will resemble...

def monkeypatchsetattr(obj, oldsetattr):
    def newsetattr(key, value):
        # hasattr(self, key) will return true if key is an attrib of baz
        # and so is not a good test
        if key is self.__dict__:
            oldsetattr(key, value)
        else:
            setattr(obj.baz, key, value)

    return newsetattr

class Baz():
    pass

class Qux():
    def __init__(self):
        self.name = None
        self.color = 'red'
        self.baz = Baz()
        self.__setattr__ = monkeypatchedselfattr(self, self.__setattr__)

    def __getattr__(self, item):
        return getattr(self.baz, item)

    def __setattr__(self, item, value):
        if hasattr(self, item):
            super(Qux, self).__setattr__(self, item, value)
        else:
            setattr(self.baz, item, value)

Problem 1 is the bigger and more immediate problem.

Is there a more elegant solution to Problem 2 after Problem 1 is resolved?

Vishal
  • 2,097
  • 6
  • 27
  • 45
  • Surely `Baz` has more going on than just `pass`? – TayTay Jun 22 '18 at 02:15
  • Yes. I've omitted all the code that seemed extraneous to wanting to set the attribute. `Baz` is a core object. `Qux` is a wrapper for `Baz`. An instance of `Baz` can be referenced by multiple `Qux` instances. – Vishal Jun 22 '18 at 02:17
  • What I'm getting at is that something in the `Baz.__getattr__` seems like it's probably circular if it's causing the maximum recursion depth. – TayTay Jun 22 '18 at 02:22
  • Can you include the `__getattr__` for Baz? – TayTay Jun 22 '18 at 02:22
  • I ran the code exactly as posted in the question. – Vishal Jun 22 '18 at 02:23

0 Answers0