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?