I have this code:
def __init__(self, a, b, c, d...):
self.a = a
self.b = b
etc
I'm thinking of replacing it with:
def __init__(self, a, b, c, d...):
args=locals()
for key in args:
self.__dict__[key] = args[key]
Is this a bad idea? Are there any better ways to do this?
Building on @ThiefMaster's comment about **kwargs
:
If you are taking in 20 arguments, it might make more sense to require your users to send arguments via keyword instead of position: with 20 arguments, there is a decent chance that someone using your code will get the arguments in the wrong order.
Consider only accepting kwargs while having a predefined list of keys you want to accept and raising a ValueError if you don't receive them. So you could use **kwargs
and then check that everything is there. E.g.
INITIAL_ARGS = set(['a','b','c','d','e'...])
def __init__(self, **kwargs):
if not INITIAL_ARGS.issubset(set(kwargs.iterkeys())):
raise ValueError("Class <myclass> requires 20 keyword arguments"
"only given %d" % len(kwargs))
self.__dict__.update(kwargs)
Not sure whether this is more or less Pythonic than your original, but it seems like it would save a ton of time later on when trying to figure out why someone using your code might be getting strange errors.
From the Zen of Python: Simple is better than complex. and Readability counts.
The explicit assignments are much more readable and simpler than using magic to set the values.
Always consider readability over clever design. Is the replacement code easier to read? I would probably just leave it. Remember that simple is better than complex. As the ThiefMaster said, the explicit assignments are more readable.
Another alternative for Python3 users: the init
decorator from drastic.
@init
def __init__(self, a, b, c, d, e, f, g, h):
# nothing to write here!