functions, optional parameters
Chris Angelico
rosuav at gmail.com
Fri May 8 08:39:17 EDT 2015
On Fri, May 8, 2015 at 9:59 PM, Michael Welle <mwe012008 at gmx.net> wrote:
> Hello,
>
> assume the following function definition:
>
> def bar(foo = []):
> print("foo: %s" % foo)
> foo.append("foo")
>
> It doesn't work like one would expect (or as I would expect ;-)). As I
> understand it the assignment of the empty list to the optional parameter
> foo take place when the function object is created, not when it is
> called. I think from the perspective of a user this is very strange.
> Anyways, what would be a good idiom to get the desired behaviour?
I'm not sure what the desired behaviour _is_, given that you're not
doing anything with the list after appending to it. But argument
defaults are evaluated when the function's defined. It's basically
like this:
DEFAULT_FOO = []
def bar(foo | nothing):
if no argument passed: foo = DEFAULT_FOO
print("foo: %s" % foo)
foo.append("foo")
There are times when this is incredibly useful, but if you don't want
this behaviour, the most common idiom is this:
def bar(foo=None):
if foo is None: foo = []
print("foo: %s" % foo)
foo.append("foo")
As an example of this, a project I'm involved in had a transition
function which could work in one of two modes:
1) Transition one file into another
2) Transition one file into another, then that into a third, then a fourth, etc
In order to maintain state cleanly, a dictionary was passed in, which
provided a "previous position" marker, which could then be updated.
For the first form, though, all I needed to do was give it an empty
dictionary, which would then be discarded. So the function went
something like this:
def transition(from, to, state=None):
if not state: state={"cursor": 0}
# ...
state["cursor"] = last_position
(I can't easily show you the code; subsequent edits meant that the
first case actually wanted to retrieve the cursor position, so it now
always has a state dict, and has no default argument. But this is
still a valid concept.)
Both idioms are very common, and you need to decide whether you want a
single mutable default, or a None default that gets replaced by a
brand new dict/list/etc every time. Just remember that the
construction of a new list is quite different from the assignment of a
pre-existing list to a new name.
ChrisA
More information about the Python-list
mailing list