-1

I received a call about stale parameters in a web app. I saw this post...

wtforms+flask today's date as a default value

... which was spot on.

The field's default was getting set on web server start. It was easy to test. A couple of print statements in the file and it was proven.

So now the senior software engineer's question is "how do I pass parameters in?".

So then ...

myfunc(offset=3):
    .... some code

fromdate = fields.DateField('From Date', default=myfunc, validators=[validators.required()])

But the senior software engineer would like to be able to inline arguments to the function at the time it is assigned like ...

fromdate = fields.DateField('From Date', default=myfunc(-10), validators=[validators.required()])

... but without invoking it immediately. Basically, storing the function object and it's arguments without executing them, still deferring so that the code runs on page load instead of at server start.

Currently, we have two ideas.

  1. The senior software engineer is looking at wrapping a method around the method. So then there is one core method and then a bunch of other ones that are scenario specific, such as myfuncminus10
  2. I'm thinking lambda expressions. Something like myfunc = lambda :datetime.now().date() - timedelta(days=365) It would definitely produce the intended outcome, but it could result in a lot of copying and pasting the same code.

What's the best way to approach this? I'm figuring that there's a pretty good way that isn't either of the two ways I just described and we just don't know it yet.

Community
  • 1
  • 1
MrGoodfix
  • 317
  • 2
  • 14
  • Within a minute 3 answers for `functools.partial`. I will delete mine. – AKS Apr 29 '16 at 18:48
  • Also see: [Partial application](https://en.wikipedia.org/wiki/Partial_application) and [Currying](https://en.wikipedia.org/wiki/Currying) – Lukas Graf Apr 29 '16 at 19:04

3 Answers3

2

You are describing an existing feature - functools.partial:

from functools import partial

fromdate = fields.DateField('From Date', default=partial(myfunc, offset=-10), validators=[validators.required()])
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • awesome! thanks for the heads up. How does this compare with the lamda expression posted by Alex Hall below? – MrGoodfix May 03 '16 at 20:21
  • There are some subtle (early-/late-binding/stack frame related) differences (read e.g. [this thread](http://stackoverflow.com/questions/3252228/python-why-is-functools-partial-necessary) for reference), but for the case at hand, I am fairly certain that you can use either one without noticing a difference. – user2390182 May 04 '16 at 07:42
  • man, I wish there was a way to mark multiple responses as "the" answer – MrGoodfix May 06 '16 at 03:42
1

You can easily create a callable with no arguments by just prepending with lambda:, i.e.:

fromdate = fields.DateField('From Date', default=lambda: myfunc(-10), validators=[validators.required()])
Alex Hall
  • 34,833
  • 5
  • 57
  • 89
1

It sounds like you could use functools.partial:

>>> from functools import partial
>>> fromdate = fields.DateField('From Date', default=partial(myfunc, 10), validators=[validators.required()])

More info: https://docs.python.org/2/library/functools.html#functools.partial

JoseKilo
  • 2,343
  • 1
  • 16
  • 28