Given a metaclass, or simpler, type(), the last argument stands as the class dict, the one which is in charge with class variables. I was wondering, is there a way to set instance variables from within a metaclass?
The reason I am using a metaclass is that I need to collect some variables defined on class creation and process them. But then, the result of this processing needs to be attached to each instance of the class, not to the class itself, since the result will be a list, which will differ from one instance of the class to another.
I will provide an example so it's easier to follow me.
I have a Model class, defined as follows:
class Model(object):
__metaclass__ = ModelType
has_many = None
def __init__(self, **kwargs):
self._fields = kwargs
The has_many class variable will be filled in at class definition by whatever model someone feels the need. In the __init__(), I simply assign the keywords provided at model instantiation to instance variable _fields.
I then have the ModelType metaclass:
class ModelType(type):
def __new__(cls, name, bases, dct):
if 'has_many' in dct:
dct['_restricted_fields'].append([has-many-model-name])
What I need to do here is pretty straight-forward. I check if someone defined the has_many class variable on his custom model class, then add the variable's content to a list of restricted fields.
And now comes the important part. When instantiating a model, I need _fields to be composed of both the keyword arguments used for instantiating the model and the restricted fields, as processed in the metaclass. This would be pretty easy if _fields were a class variable in the Model class, but since it is an instance variable, I don't know how can I also add the restricted fields to it.
These being said, is there any way of achieving this? Or is there a better way of handling this? (I thought of using only a metaclass and set a _restricted_fields class variable on the model, then use this variable within the class __init__() to add the restricted fields to the normal fields, but very soon the model class will be cluttered of code which, in my opinion, should rest in another part of the code).