Reputation: 8205
I've defined two classes as follows:
class ClassModel(object):
pass
class FunctionModel(object):
attr = None
def __call__(self):
return self.attr
The idea is to create several copy of ClassModel
, each one containing zero or more methods inheriting from FunctionModel
, which should have each one their own attributes.
I'm fine for creating children of ClassModel
and FunctionModel
. But I don't succeed to attach the two so that, when the children of ClassModel
are instanciated, the function-like objects derived from FunctionModel
which have been attached to them are recognized by Python as their methods.
See what happens
>>> func = type('func', (FunctionModel,), {'attr': 'someattr'})
>>> func_inst = func()
>>> func_inst
<__main__.func object at 0x968e4ac>
>>> Cls = type('Cls', (ClassModel,), {'func_inst': func_inst})
>>> cls_inst = Cls()
>>> cls_inst.func_inst
<__main__.func object at 0x968e4ac>
How can I go with this ?
Upvotes: 1
Views: 101
Reputation: 5534
Consider using metaclasses, here an example:
class ClassModel(object):
attr = None
class FunctionModel(object):
attr = None
def __init__(self,aValue):
self.attr = aValue
def __call__(self, cls):
return self.attr + cls.attr
def getFMClasses(aDictOfMethods):
class MM(type):
def __new__(cls, name, bases, dct):
for aName in aDictOfMethods:
dct[aName] = classmethod(FunctionModel(aDictOfMethods[aName]))
return super(MM, cls).__new__(cls, name, bases, dct)
pass
pass
return MM
Once all that is defined, getting new classes is a child game...
class NewClass1(ClassModel):
__metaclass__ = getFMClasses({'method1':3,'method2':5})
attr = 2
class NewClass2(ClassModel):
__metaclass__ = getFMClasses({'method1':6,'DifferentMethod':2,'OneMore':0})
attr = 3
myObj = NewClass1()
print myObj.method1()
print myObj.method2()
myObj = NewClass2()
print myObj.method1()
print myObj.DifferentMethod()
print myObj.OneMore()
Upvotes: 2
Reputation: 8205
I finally figured out how to do this. Class methods are added after the new class object is created (which is not exactly what I wanted), but before it is actually instanciated. Name of methods can be changed dynamically thanks to setattr
.
class ClassModel(object):
number = None
class FunctionModel(object):
number = None
def __call__(myself, clsself):
return myself.number + clsself.number
Define the class and add it attributes:
from types import MethodType
func1 = type('func1', (FunctionModel,), {'number': 3})
func2 = type('func2', (FunctionModel,), {'number': 5})
func1_inst = func1()
func2_inst = func2()
Cls = type('Cls', (ClassModel,), {'number': 10})
setattr(Cls, 'func1', MethodType(func1_inst, Cls))
setattr(Cls, 'func2', MethodType(func2_inst, Cls))
And instanciate it:
cls_inst = Cls()
cls_inst.func1()
# 13
cls_inst.func2()
# 15
Upvotes: 0
Reputation: 20341
I may be completely wrong here, but surely you just want FunctionModel
to be the parent class of ClassModel
?
class FunctionModel(object):
attr = None
def __call__(self):
return self.attr
class ClassModel(FunctionModel):
pass
Now ClassModel
will have all the attributes of FunctionModel
but beware of over-riding stuff. When creating an __init__
method for ClassModel
you can make sure you call FunctionModel
s __init__
too with a super()
class ClassModel(FunctionModel):
def __init__(self, extra_args):
super(ClassModel, self).__init__()
self.extra_args = extra_args
More information on python classes and inheritance here.
Upvotes: 0