I am not sure if this fits exactly what you want, but basically you can let C decide what to give to A, B and let A, B decide what to use, using **kwds method parameters in A and B.
One of the differences, with the sample class C2, is that, if C has a different default value it overrides A, B.
There is also another alternative, under C3, where you use a guard value (not using None to allow that to be a default) to only pass on arguments that were given to C3.
class A:
def __init__(self, one=1, two=2, **kwds):
self.one = one
self.two = two
def do_smt(self):
pass
class B:
def __init__(self, value="test", **kwds):
self.value = value
class C:
def __init__(self, one=1, two=2, value="test"):
self.A = A(one, two)
self.B = B(value)
class C2:
""" your default values override those of A, B"""
def __init__(self, one=1, two=2, value="test"):
locals_ = locals()
locals_.pop("self")
self.A = A(**locals_)
self.B = B(**locals_)
undefined = NotImplemented
class C3:
""" your default values dont affect A and Bs"""
def __init__(self, one=undefined, two=undefined, value="test"):
locals_ = {k:v for k,v in locals().items() if k != "self" and v is not undefined}
self.A = A(**locals_)
self.B = B(**locals_)
#can still use it locally
self.one = one if one is not undefined else 11
self.two = two if two is not undefined else 22
c= C()
print("c.A.one:", c.A.one)
print("c.B.value:", c.B.value)
c2= C2()
print("c2.A.one:", c2.A.one)
print("c2.B.value:", c2.B.value)
c3= C3()
print("c3.A.one:", c3.A.one)
print("c3.one:", c3.one)
print("c3.B.value:", c3.B.value)
output:
c.A.one: 1
c.B.value: test
c2.A.one: 1
c2.B.value: test
c3.A.one: 1
c3.one: 11
c3.B.value: test
You could even have a variant of C that uses **kwds itself and pass those on to A, B in case they find value in it.
class C4:
""" your default values dont affect A and Bs
and you can pass in anything.
Neither two or value are known to C and that's OK"""
def __init__(self, one=undefined, **kwds):
locals_ = locals()
locals_ = {k:v for k,v in locals().items() if k not in ("self","kwds") and v is not undefined}
locals_.update(**kwds)
self.A = A(**locals_)
self.B = B(**locals_)
#can still use it locally
self.one = one if one is not undefined else 11
c4= C4(value="somevalue")
print("c4.A.one:", c4.A.one)
print("c4.A.two:", c4.A.two)
print("c4.one:", c4.one)
print("c4.B.value:", c4.B.value)
output:
c4.A.one: 1
c4.A.two: 2
c4.one: 11
c4.B.value: somevalue