Extending a class by parameter in Python
Clash Royale CLAN TAG#URR8PPP
up vote
15
down vote
favorite
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()
python class inheritance closures
add a comment |Â
up vote
15
down vote
favorite
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()
python class inheritance closures
2
At what point isBar
known?class Foo(X):
works just fine even ifX
is a variable, not the literal name of the parent class.
– jasonharper
Aug 12 at 21:12
I should point out that, in order forsuper_cool_function
to be callable by an instance of Foo, it'd need theself
parameter (def super_cool_function(self):
). I'm not going to edit your question to correct it, because that would invalidate abarnert's answer.
– coldspeed
Aug 13 at 3:16
You can also consider the strategy pattern: sourcemaking.com/design_patterns/strategy/python/1
– Tjorriemorrie
Aug 30 at 23:50
add a comment |Â
up vote
15
down vote
favorite
up vote
15
down vote
favorite
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()
python class inheritance closures
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()
python class inheritance closures
edited Aug 13 at 3:15


coldspeed
102k1787153
102k1787153
asked Aug 12 at 21:09


Ivy F.
804
804
2
At what point isBar
known?class Foo(X):
works just fine even ifX
is a variable, not the literal name of the parent class.
– jasonharper
Aug 12 at 21:12
I should point out that, in order forsuper_cool_function
to be callable by an instance of Foo, it'd need theself
parameter (def super_cool_function(self):
). I'm not going to edit your question to correct it, because that would invalidate abarnert's answer.
– coldspeed
Aug 13 at 3:16
You can also consider the strategy pattern: sourcemaking.com/design_patterns/strategy/python/1
– Tjorriemorrie
Aug 30 at 23:50
add a comment |Â
2
At what point isBar
known?class Foo(X):
works just fine even ifX
is a variable, not the literal name of the parent class.
– jasonharper
Aug 12 at 21:12
I should point out that, in order forsuper_cool_function
to be callable by an instance of Foo, it'd need theself
parameter (def super_cool_function(self):
). I'm not going to edit your question to correct it, because that would invalidate abarnert's answer.
– coldspeed
Aug 13 at 3:16
You can also consider the strategy pattern: sourcemaking.com/design_patterns/strategy/python/1
– Tjorriemorrie
Aug 30 at 23:50
2
2
At what point is
Bar
known? class Foo(X):
works just fine even if X
is a variable, not the literal name of the parent class.– jasonharper
Aug 12 at 21:12
At what point is
Bar
known? class Foo(X):
works just fine even if X
is a variable, not the literal name of the parent class.– jasonharper
Aug 12 at 21:12
I should point out that, in order for
super_cool_function
to be callable by an instance of Foo, it'd need the self
parameter (def super_cool_function(self):
). I'm not going to edit your question to correct it, because that would invalidate abarnert's answer.– coldspeed
Aug 13 at 3:16
I should point out that, in order for
super_cool_function
to be callable by an instance of Foo, it'd need the self
parameter (def super_cool_function(self):
). I'm not going to edit your question to correct it, because that would invalidate abarnert's answer.– coldspeed
Aug 13 at 3:16
You can also consider the strategy pattern: sourcemaking.com/design_patterns/strategy/python/1
– Tjorriemorrie
Aug 30 at 23:50
You can also consider the strategy pattern: sourcemaking.com/design_patterns/strategy/python/1
– Tjorriemorrie
Aug 30 at 23:50
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
22
down vote
accepted
"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
add a comment |Â
up vote
4
down vote
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
1
Any reason why you usedobject.__setattr__
instead ofsuper().__setattr__
?
– Aran-Fey
Aug 12 at 21:23
@Aran-Fey Probably just habit left over from Guido's original Python 2.2 examples or something, and I can't see any good reason not to usesuper
, so… edited.
– abarnert
Aug 12 at 21:25
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
22
down vote
accepted
"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
add a comment |Â
up vote
22
down vote
accepted
"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
add a comment |Â
up vote
22
down vote
accepted
up vote
22
down vote
accepted
"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
"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
edited Aug 13 at 3:21
answered Aug 12 at 21:14


coldspeed
102k1787153
102k1787153
add a comment |Â
add a comment |Â
up vote
4
down vote
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
1
Any reason why you usedobject.__setattr__
instead ofsuper().__setattr__
?
– Aran-Fey
Aug 12 at 21:23
@Aran-Fey Probably just habit left over from Guido's original Python 2.2 examples or something, and I can't see any good reason not to usesuper
, so… edited.
– abarnert
Aug 12 at 21:25
add a comment |Â
up vote
4
down vote
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
1
Any reason why you usedobject.__setattr__
instead ofsuper().__setattr__
?
– Aran-Fey
Aug 12 at 21:23
@Aran-Fey Probably just habit left over from Guido's original Python 2.2 examples or something, and I can't see any good reason not to usesuper
, so… edited.
– abarnert
Aug 12 at 21:25
add a comment |Â
up vote
4
down vote
up vote
4
down vote
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
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
edited Aug 12 at 21:29
answered Aug 12 at 21:21
abarnert
241k21327430
241k21327430
1
Any reason why you usedobject.__setattr__
instead ofsuper().__setattr__
?
– Aran-Fey
Aug 12 at 21:23
@Aran-Fey Probably just habit left over from Guido's original Python 2.2 examples or something, and I can't see any good reason not to usesuper
, so… edited.
– abarnert
Aug 12 at 21:25
add a comment |Â
1
Any reason why you usedobject.__setattr__
instead ofsuper().__setattr__
?
– Aran-Fey
Aug 12 at 21:23
@Aran-Fey Probably just habit left over from Guido's original Python 2.2 examples or something, and I can't see any good reason not to usesuper
, so… edited.
– abarnert
Aug 12 at 21:25
1
1
Any reason why you used
object.__setattr__
instead of super().__setattr__
?– Aran-Fey
Aug 12 at 21:23
Any reason why you used
object.__setattr__
instead of super().__setattr__
?– Aran-Fey
Aug 12 at 21:23
@Aran-Fey Probably just habit left over from Guido's original Python 2.2 examples or something, and I can't see any good reason not to use
super
, so… edited.– abarnert
Aug 12 at 21:25
@Aran-Fey Probably just habit left over from Guido's original Python 2.2 examples or something, and I can't see any good reason not to use
super
, so… edited.– abarnert
Aug 12 at 21:25
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51812872%2fextending-a-class-by-parameter-in-python%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
2
At what point is
Bar
known?class Foo(X):
works just fine even ifX
is a variable, not the literal name of the parent class.– jasonharper
Aug 12 at 21:12
I should point out that, in order for
super_cool_function
to be callable by an instance of Foo, it'd need theself
parameter (def super_cool_function(self):
). I'm not going to edit your question to correct it, because that would invalidate abarnert's answer.– coldspeed
Aug 13 at 3:16
You can also consider the strategy pattern: sourcemaking.com/design_patterns/strategy/python/1
– Tjorriemorrie
Aug 30 at 23:50