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?
BranchandLeafinstances to be class variables inRootandBranchclasses respectively?Roota bunch ofBranches andLeafs need to be duplicated.Branch(you can use__getattr__for evaluating missing values).