Is there a nice Python idiom for constructors which would expedite the
following?
class Foo:
def __init__(self, a,b,c,d,...):
self.a = a
self.b = b
self.c = c
self.d = d
...
I would like to keep the __init__ parameter list explicit, as is,
rather than passing in a dictionary, as I want the code to be explicit
about what arguments it expects... in effect enforcing the right number
of arguments.
Well, it's hard to automate it and keep the parameter list explicit,
but you could do this, of course:
class Foo:
def __init__(self, *args):
maps = zip(('a','b','c','d'), args[:4])
for map in maps:
setattr(self, map[0], map[1])
Which *will* limit the arguments to the ones specified. As an additional
tweak, you could make this a base class and put the argument list in
the subclass to hide the magic:
class Args:
argspec = ()
def __init__(self, *args):
maps = zip(self.argspec, args[:len(self.argspec)])
for map in maps:
setattr(self, map[0], map[1])
class Foo(Args):
argspec = ('a', 'b', 'c', 'd')
Or even better, use a method, so you can customize:
class Args:
argspec = ()
def _get_args(self, *args):
maps = zip(self.argspec, args[:len(self.argspec)])
for map in maps:
setattr(self, map[0], map[1])
class Foo(Args):
argspec = ('a', 'b', 'c', 'd')
def __init__(self, *args):
self._get_args(*args)
This version silently ignores extra arguments, but you might
want to raise an exception instead:
class Args:
argspec = ()
def _get_args(self, *args):
expected = len(self.argspec)
given = len(args)
if expected != given:
raise TypeError("__init__ takes exactly %d arguments (%d given)" % (expected, given))
maps = zip(self.argspec, args[:expected])
for map in maps:
setattr(self, map[0], map[1])
Using this, I get the following response to too many arguments:
File "<stdin>", line 1, in ?
File "<stdin>", line 4, in __init__
File "<stdin>", line 7, in _get_args
TypeError: __init__ takes exactly 4 arguments (5 given)
HTH
Cheers,
Terry