Explicit is better than implicit. The idiomatic way to handle composition is using "mixins":
class MyFooMixin():
def foo(self):
print("I have a foo")
class MyBarMixin():
def bar(self):
print("This is a bar, where is my beer?")
class MyObject(MyFooMixin, MyBarMixin):
pass
>>> x = MyObject()
>>> x.foo()
I have a foo
>>> x.bar()
This is a bar, where is my beer?
That said, at some implementations you can inspect the current frame. This is a naive approach to get you started (I'm sure it is wrong but I don't feel like digging all the frame structure stuff in order to write a proper implementation):
class Foo(object):
_instantiators = []
def __init__(self):
try:
raise Exception("foo")
except Exception as foo:
for frame in reversed(inspect.stack()):
try:
for line in frame[4]:
if line.startswith('class '):
class_name = re.match(r'class\s+(\S+?)\(', line).group(1)
self._instantiators.append(frame[0].f_globals[class_name])
break
except (IndexError, TypeError):
pass
class Bar(object):
foo = Foo()
if __name__ == '__main__':
bar = Bar()
print Foo._instantiators
This abominable hack will print:
[<class '__main__.Bar'>]
This is probably wrong in so many ways, but Python is very hackable (my second programming language was Lisp, after BASIC, in Python I miss lispy features like hygienic macros and tail call optimization).