2

Example

Take the following example

class Leaf:
    def __get__(self, instance, owner):
        if instance is None:
            return self

        # TODO How to access Root.value here?


class Branch:
    bar = Leaf()


class Root:
    foo = Branch()

    def __init__(self, value):
        self.value = value


if __name__ == '__main__':
    x = Root(20)
    y = Root(30)

    print(x.foo.bar)  # 20

    a = x.foo

    print(a.bar)  # 20
    print(y.foo.bar)  # 30
    print(a.bar)  # 20

In Leaf.__get__ instance points to the Branch instance. However, I need to access value, which is an instance member of Root.

Background

My task is to write a parser for a large file header. The parser shall be robust and fast. Therefore, instead of parsing the whole header structure, I proposed to use descriptors to lazy parse the fields. This allows for decoding/encoding the header fields only when required. So, there's a root object that holds the complete header as a bytearray and when a field is accessed, its descriptor reads from or writes to this bytearray. However, the header structure is hierarchical and contains nested fields. For that reason I need to access the roots bytearray from a nested descriptor.

Related questions and solutions

Similar questions about instance descriptors have been raised before.

1. Create a per instance

The solution would be to add the descriptors to the instances instead of classes and set the shared value as reference. IMO this seems a bit inefficient.

See Dynamically adding @property in python and Python - How to pass instance variable value to descriptor parameter?

2. Override __getattribute__

I don't think this would work, since __getattribute__ of Branch doesn't know about the Root instance.

3. Propagate value

While traversing the structure, Branch.__get__ gets called, where we could store a reference to the root instance, which is accessible from Leaf.__get__. However, this will not work if we mix up calls on multiple instances of Root.


Finally, my question is if there are better solutions for this specific problem?

Manuel L
  • 29
  • 1
  • 5
  • Do you need `Branch` and `Leaf` instances to be class variables in `Root` and `Branch` classes respectively? – nisemonoxide Feb 07 '18 at 22:57
  • Listed as the first solution in _Related questions_ it might be a solution to use instance descriptors instead of class descriptors. However, I think this would increase the memory footprint a lot, since for every instance of `Root` a bunch of `Branch`es and `Leaf`s need to be duplicated. – Manuel L Feb 07 '18 at 23:03
  • I don't think you can do it given the constraints without involving some traceback magic to get the root instance from parent frames. I would suggest not using nested descriptors if memory is such a big concern, but implementing the logic in `Branch` (you can use `__getattr__` for evaluating missing values). – Krzysztof Bujniewicz Feb 07 '18 at 23:24

0 Answers0