I want to expand the class Foo
by the class Bar
, the issue that I have is that I can't expand it in the usual way (class Foo(Bar)
) because the class Bar
is somewhat dynamically generated.
I made this small example to illustrate my desired outcome:
class Bar:
def super_cool_function():
print("Cool")
class Foo:
def __init__(self, another_class):
# I want to extend Foo by another_class
# Desired result
foobar = Foo(Bar)
foobar.super_cool_function()
Again this is not what I'm looking for:
class Foo(Bar):
pass
foobar = Foo()
foobar.super_cool_function()
Absolutely. Options include, but aren't limited to, these: Implementing an interpreter where the programmer can define types.
In Python a class can inherit from more than one class. If a class inherits, it has the methods and variables from the parent classes. In essence, it's called multiple inheritance because a class can inherit from multiple classes.
Python issubclass() is built-in function used to check if a class is a subclass of another class or not. This function returns True if the given class is the subclass of given class else it returns False . Return Type: True if object is subclass of a class, or any element of the tuple, otherwise False.
The way to "avoid" inheritance here would be to rename _private_var and make it a class-private name. i.e. __private_var . If you do this, running your code will cause an AttributeError: 'Child' object has no attribute '_Parent__private_var' (note the _Parent prefix automatically added).
"The class Bar
is somewhat dynamically generated" That's fine... as long as it follows the blueprint (of a class that should be extended by Foo
), you can leverage python closures here. Dynamically create a new class by creating it inside, and returning it from a function.
def get_class(superclass):
class Foo(superclass):
def __init__(self, ...):
...
return Foo
DynamicFoo = get_class(Bar)
myobj = DynamicFoo()
This is a common pattern you'll see in python - leveraging closures to dynamically create callbacks and classes.
The answer above assumes that Bar
is correctly defined, when it in fact is not. The super_cool_function
is missing a self parameter. Instance methods are always called with the first parameter (the instance itself) automatically being passed in as the first attribute.
So, the correct definition for Bar
would be:
class Bar:
def super_cool_function(self):
print("Cool")
Now, defining get_class
with the simplest definition of the inner class Foo
:
def get_class(superclass):
class Foo(superclass):
pass
return Foo
DynamicFoo = get_class(Bar)
myobj = DynamicFoo()
myobj.super_cool_function()
# Cool
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With