I sometimes do this for classes that act "grouped", i.e. they have a bunch of custom attributes:
class SuperClass(object): def __init__(self, **kw): for name, value in kw.iteritems(): if not hasattr(self, name): raise TypeError('Unexpected argument: %s' % name) setattr(self, name, value) class SubClass(SuperClass): instance_var = None
Then you can call SubClass2(instance_var=[], other_instance_var=False) , and it will work without defining __init__ in any of them. You can also use any property. Although this allows you to rewrite methods that you probably did not intend to (since they will return True for hasattr() as an instance variable).
If you add any property or other descriptor, it will work fine. You can use this for type checking; unlike type checking in __init__ , it will be applied at any time when this value is updated. Note that you cannot use any positional arguments for them unless you override __init__ , so sometimes what would be a natural positional argument will not work. formencode.declarative covers this and other problems, perhaps with care I would not suggest you try (in retrospect, I don't think it's worth it).
Please note that any recipe that uses self.__dict__ will not respect properties and descriptors, and if you use them together, you will get simply strange and unexpected results. I recommend using setattr() to set attributes, never self.__dict__ .
Also, this recipe does not provide a very useful signature, while some of those that perform personnel and functional introspection do. With some work, you can dynamically generate __doc__ , which clarifies the arguments ... but again I'm not sure if the gain is to add more moving parts.
source share