Code first
The goal is to design OuterBase
such that the following passes:
class Outer(OuterBase):
def __init__(self, foo: str) -> None:
self.foo = foo
class Inner:
outer: Outer
def get_foo(self) -> str:
return self.outer.foo
inner = Outer("bar").Inner()
assert inner.get_foo() == "bar"
My question is closely related to this: How to access outer class from an inner class?
But it is decisively different in one relevant nuance. That question is about how to access an outer class from inside the inner class. This question is about access to a specific instance of the outer class.
Question
Given an Outer
and an Inner
class, where the latter is defined in the body of the former, and given an instance of Outer
, can we pass that instance to the Inner
constructor so as to bind the Inner
instance to that Outer
instance?
So if we did outer = Outer()
and then inner = outer.Inner()
, there would then be a reference to outer
in an attribute of inner
.
Secondary requirements
1) Simplest possible usage (minimal boilerplate)
It would be ideal, if the entire logic facilitating this binding of the instances were "hidden" in the Outer
class.
Then there would be some OuterBase
class that a user could inherit from and all he would have to do, is define the Inner
class (with the agreed upon fixed name) and expect its outer
attribute (also agreed upon) to hold a reference to an instance of the outer class.
Solutions involving decoration of the inner class or explicitly passing it a meta class or defining a special __init__
method and so on would be considered sub-optimal.
2) Type safety (to the greatest degree possible)
The code (both of the implementation and the usage) should ideally pass mypy --strict
checks and obfuscate dynamic typing as little as possible.
Hypothetical real-life use case
Say the inner class is used as a settings container for instances of the outer class, similar to how Pydantic is designed. In Pydantic (possibly for various reasons) the inner Config
class is a class-wide configuration, i.e. it applies to all instances of the model (outer class). With a setup like the one I am asking about here the usage of Pydantic models would remain unchanged, but now deviations in configuration would be possible on an instance level by binding a specific Config
instance to a specific model instance.