DRY functions with named attributes used as default arguments
Arnaud Delobelle
arnodel at gmail.com
Sun Oct 9 09:19:34 EDT 2011
On 9 October 2011 13:20, Tim Chase <python.list at tim.thechases.com> wrote:
> My intent is to have a function object something like
>
> def foo(arg1, arg2=foo.DEFAULT):
> return int(do_stuff(arg1, arg2))
> foo.SPECIAL = 42
> foo.MONKEY = 31415
> foo.DEFAULT = foo.SPECIAL
>
> so I can call it with either
>
> result = foo(myarg)
>
> or
>
> result = foo(myarg, foo.SPECIAL)
>
> However I can't do this because foo.DEFAULT isn't defined at the time the
> function is created. I'd like to avoid hard-coding things while staying
> DRY, so I don't like
>
> def foo(arg1, arg2=42)
>
> because the default might change due to business rule changes, I have a
> dangling "magic constant" and if the value of SPECIAL changes, I have to
> catch that it should be changed in two places.
>
> My current hack/abuse is to use __new__ in a class that can contain the
> information:
>
> class foo(object):
> SPECIAL = 42
> MONKEY = 31415
> DEFAULT = SPECIAL
> def __new__(cls, arg1, arg2=DEFAULT):
> return int(do_stuff(arg1, arg2))
>
> i1 = foo("spatula")
> i2 = foo("tapioca", foo.MONKEY)
>
> 1) is this "icky" (a term of art ;-)
> 2) or is this reasonable
> 3) or is there a better way to do what I want?
>
Why do you want these argument values to be attributes of the function?
Anyway, simpler than abusing classes:
foo_default = 42
def foo(arg1, arg2=foo_default):
...
foo.DEFAULT = foo_default
del foo_default
...
Or get the default at function runtime:
def foo(arg1, arg2=None):
if arg2 is None:
arg2 = foo.DEFAULT
...
foo.DEFAULT = 42
...
But I'd probably simply go for foo_DEFAULT, foo_MONKEY and
foo_SPECIAL. They're also quicker (1 dict lookup instead of 2)
--
Arnaud
More information about the Python-list
mailing list