2009-09-14

Class Constructor Decorator

While Python is already very terse there are still some repetition that can be worked out. I'm going to talk about class constructors here. Many a class init method is little else but adding the init parameters as instance attributes, I have written a constructor that takes care of that, this preliminary version dumps everything as public attributes in the instance. IFF I need more customization, I'll write the full implementation I was meaning yesterday:

constructor.py

#!/usr/bin/env python
"""
@author rgz
A decorator for converting the constructor arguments into instance attributes automatically.
"""
import decorator
import inspect
@decorator.decorator
def constructor(init, *args, **kwargs):
"""Converts the constructor arguments into instance attributes automatically"""
names, args_name, kwargs_name, defaults = inspect.getargspec(init)
assert len(names) > 0, "Methods should have at least 1 argument!"
for i, name in enumerate(names):
if i:
setattr(self, name, args[i])
else:
self = args[i]
if args_name:
setattr(self, args_name, args[i + 1:])
if kwargs_name:
setattr(self, kwargs_name, kwargs)
init(*args, **kwargs)
__all__ = ['constructor']
if __name__ == '__main__':
class Spam(object):
@constructor
def __init__(
self,
positional_argument_1,
positional_argument_2,
default_argument = 'default value',
*variable_arguments,
**keyword_arguments
):
self.variable_arguments = list(self.variable_arguments) # Attributes already set
spam = Spam(
'first argument',
'second argument',
'non default value',
'first variable value',
'second variable value',
keyword_argument_1 = 'first keyword value',
keyword_argument_2 = 'second keyword value',
)
assert spam.positional_argument_1 == 'first argument'
assert spam.positional_argument_2 == 'second argument'
assert spam.default_argument == 'non default value'
assert type(spam.variable_arguments) is list
assert spam.variable_arguments[0] == 'first variable value'
assert spam.variable_arguments[1] == 'second variable value'
assert spam.keyword_arguments['keyword_argument_1'] == 'first keyword value'
assert spam.keyword_arguments['keyword_argument_2'] == 'second keyword value'

Update: I posted this on reddit because I wanted to know if someone needed something like that but apparently I must have done something really bad, I've been modded -1 and have received no comments.