What is a function parameter =[] for?
BartC
bc at freeuk.com
Thu Nov 19 08:19:25 EST 2015
On 19/11/2015 12:19, Steven D'Aprano wrote:
> On Thu, 19 Nov 2015 10:14 am, BartC wrote:
> Consider this pair of functions:
>
>
> def expensive():
> # Simulate some expensive calculation or procedure.
> time.sleep(100)
> return random.randint(1, 6)
>
>
> def demo(arg=expensive()):
> return arg + 1
>
>
> Now we call the second function four times, without an argument so that the
> default value is used:
>
> demo()
> demo()
> demo()
> demo()
>
> What results do you expect?
If someone /wants/ expensive() to be called each time, then why not? If
they don't, then it seems easy enough to write:
demo_default=expensive()
def demo(arg=demo_default):
...
(As you mention later...)
> - if the language defaults to early binding, it is *easy* for the
> programmer to get late binding semantics;
>
> - if the language defaults to late binding, it is *very difficult*
> for the programmer to get early binding semantics.
I got the impression that Python was a nice, easy language for everyone
to use. Not one where you need a Master's degree in CS to understand the
nuances of! And to understand why something that is so blindingly
obvious doesn't work.
> But let's try going the other way. Suppose function defaults were evaluated
> each and every time you called the function. How could you *avoid* the
> expense and waste of re-evaluating the default over and over again?
I use default parameters a lot in other languages.
99% of the time the default value is a constant. And most often that
constant is 0, "" or an empty list.
You want these very common examples to /just work/ instead of going to
lengths trying to explain why they don't.
> You can't, or at least, not cleanly and easily. The most obvious way is to
> use a global variable:
>
> ARG = expensive()
>
> def demo(arg=ARG):
> ...
>
> This is ... horrible. You are still evaluating the default each time,
I implement an interpreted language where these calls:
demo()
demo(ARG)
would have exactly the same cost.
I understand that Python is very different: at the call-site, the
compiler has no idea of the number of arguments a function defines or
what the default values might be, or even if it is a function that is
being called.
But even under those circumstances, I would endeavour to make such a
function call as fast as is practical.
(That could involve a runtime check on number of parameters,
substituting the equivalent of None for missing ones, or whatever
default expression has been declared.
But here, I am benefiting from my language not being Python which does
seem to like making things difficult.)
> but at
> least it is only a global variable lookup,
Maybe you can wrap the entire module inside a function? Other than a bit
at the end that calls that function. Does that solve the global lookup
problem?
> When you deal with mutable objects, you have to expect them to mutate. The
> whole point of mutability is that their value can change.
That [] doesn't look like an object that could change. It looks like an
empty list constructor. You would expect a constructor for an empty list
to yield an empty list throughout a program! (As it does, in most other
contexts.)
You presumably think differently because you have some inside knowledge
of how Python works, and know that that [] undergoes a one-time
assignment to a local, persistent 'default' variable where it's value
can indeed by changed. (Thanks to another Python feature where an
assignment is a very shallow copy of an object.) And it is that volatile
variable that is the actual default.
But not everyone is going to know that.
--
Bartc
More information about the Python-list
mailing list