Your desired use is a little strange:
foobar = Foo(Bar)
You're constructing a Foo instance by handing it the Bar class object, and expecting to get back something that acts like a Bar instance. Normally, a proxy class is designed to take an object to proxy to, or look on up somewhere, not just construct one with no arguments.
But, other than that oddness, which just means an __init__ method that constructs the object, this is just a bog-standard proxy class. So:
class Foo:
def __init__(self, cls):
self._inst = cls()
def __getattr__(self, name):
return getattr(self._inst, name)
def __setattr__(self, name, value):
if name in {'_inst'}:
super().__setattr__(name, value)
else:
setattr(self._inst, name, value)
def __delattr__(self, name):
delattr(self._inst, name)
Of course you still won't be able to call that super_cool_function on a foobar any more than you could on a Bar instance, because it's defined as a method and doesn't have a self parameter. But you'll get the same error from the Foo instance that you would have gotten from a Bar instance:
>>> foobar.super_cool_function
<bound method Bar.super_cool_function of <__main__.Bar object at 0x129f95080>>
>>> foobar.super_cool_function()
TypeError: super_cool_function() takes 0 positional arguments but 1 was
Barknown?class Foo(X):works just fine even ifXis a variable, not the literal name of the parent class.super_cool_functionto be callable by an instance of Foo, it'd need theselfparameter (def super_cool_function(self):). I'm not going to edit your question to correct it, because that would invalidate abarnert's answer.