A
Andrew Dalke
Alex
A "clever" (a-hem solution can use decorators.
It's hard to make the call signature correct though.
Here's a hack solution using exec, which is the wrong
way to do it. For example, it gets the nested scope
wrong for the context of the original function. But
I'm not Raymond Hettinger and I can't fiddle Python's
byte code well enough for a more correct solution.
# Ugly hack! Do not use this! Only for grins!
def store_args(f):
co = f.func_code
# I think this is right way to get the parameter list
argnames = co.co_varnames[:co.co_argcount]
if argnames[:1] != ("self",):
raise TypeError("first parameter must be 'self'")
argnames = argnames[1:]
argdef = list(argnames)
if f.func_defaults:
start = len(argnames) - len(f.func_defaults)
for i in range(len(f.func_default)):
argdef[start+i] = "%s = _defaults[%s]" % (argdef[start+i], i)
lines = ["def %s(self, %s):" % (f.func_name, ", ".join(argdef))]
for argname in argnames:
lines.append(" self.%s = %s" % (argname, argname))
lines.append(" return __func(self, %s)\n" %
(", ".join(argnames), ))
code = "\n".join(lines)
g = f.func_globals.copy()
g["__func"] = f
d = {"_defaults": f.func_defaults}
exec code in g, d
return d[f.func_name]
class Spam:
@store_args
def __init__(self, x, y, z):
pass
Andrew
(e-mail address removed)
Ah, sorry, my favourite idiom to avoid the boilerplate of
def __init__(self, fee, fie, foo, fum):
self.fee = fee
self.fie = fie
self.foo = foo
self.fum = fum
A "clever" (a-hem solution can use decorators.
It's hard to make the call signature correct though.
Here's a hack solution using exec, which is the wrong
way to do it. For example, it gets the nested scope
wrong for the context of the original function. But
I'm not Raymond Hettinger and I can't fiddle Python's
byte code well enough for a more correct solution.
# Ugly hack! Do not use this! Only for grins!
def store_args(f):
co = f.func_code
# I think this is right way to get the parameter list
argnames = co.co_varnames[:co.co_argcount]
if argnames[:1] != ("self",):
raise TypeError("first parameter must be 'self'")
argnames = argnames[1:]
argdef = list(argnames)
if f.func_defaults:
start = len(argnames) - len(f.func_defaults)
for i in range(len(f.func_default)):
argdef[start+i] = "%s = _defaults[%s]" % (argdef[start+i], i)
lines = ["def %s(self, %s):" % (f.func_name, ", ".join(argdef))]
for argname in argnames:
lines.append(" self.%s = %s" % (argname, argname))
lines.append(" return __func(self, %s)\n" %
(", ".join(argnames), ))
code = "\n".join(lines)
g = f.func_globals.copy()
g["__func"] = f
d = {"_defaults": f.func_defaults}
exec code in g, d
return d[f.func_name]
class Spam:
@store_args
def __init__(self, x, y, z):
pass
Andrew
(e-mail address removed)