I am making a python program which is using classes, I want one class to only selectively inherit from another e.g:
class X(object):
def __init__(self):
self.hello = 'hello'
class Y(object):
def __init__(self):
self.moo = 'moo'
class Z():
def __init__(self, mode):
if mode == 'Y':
# Class will now Inherit from Y
elif mode == 'X':
# Class will now Inherit for X
How can I do this without making another class?
-
2Can you please give a little more info as to why you want it to be this way? As a design decision it seems a little odd to me, given these bare facts.StoryTeller - Unslander Monica– StoryTeller - Unslander Monica2012年09月19日 09:36:00 +00:00Commented Sep 19, 2012 at 9:36
4 Answers 4
In Python classes can be created at run-time:
class X(object):
def __init__(self):
self.hello = 'hello'
class Y(object):
def __init__(self):
self.moo = 'moo'
def create_class_Z(mode):
base_class = globals()[mode]
class Z(base_class):
def __init__(self):
base_class.__init__(self)
return Z
ZX = create_class_Z('X')
zx = ZX()
print(zx.hello)
ZY = create_class_Z('Y')
zy = ZY()
print(zy.moo)
Comments
You can do this by overriding __new__ and changing the cls passed in (you're creating a new type by appending X or Y as a base class):
class X(object):
def __init__(self):
self.hello = 'hello'
class Y(object):
def __init__(self):
self.moo = 'moo'
class Z(object):
def __new__(cls, mode):
mixin = {'X': X, 'Y': Y}[mode]
cls = type(cls.__name__ + '+' + mixin.__name__, (cls, mixin), {})
return super(Z, cls).__new__(cls)
def __init__(self, mode, *args, **kwargs):
super(Z, self).__init__(*args, **kwargs)
Note that you need to bypass Z.__new__ using super to avoid infinite recursion; this is the standard pattern for __new__ special override methods.
7 Comments
__new__ has the advantage of keeping relevant code together and retaining compatibility with existing code.Z anywhere (e.g. in Z methods with super, in other code accessing static methods or static members, monkeypatching in tests) then all that code expects Z to be the actual class.Z would break; my solution works absolutely fine for that usage.I think you'd better define two members within Z,one is a class instance of X,another is a instance of Y.You can get the associated information stored in these instances while use different mode.
1 Comment
A solution using type:
class _Z(): pass #rename your class Z to this
def Z(mode): #this function acts as the constructor for class Z
classes = {'X': X, 'Y': Y, 'Foo': Bar} #map the mode argument to the base cls
#create a new type with base classes Z and the class determined by mode
cls = type('Z', (_Z, classes[mode]), {})
#instantiate the class and return the instance
return cls()
6 Comments
isinstance(Z('X'), Z).isinstance(Z('X'), _Z) if it is absolutely needed.