list parameter of a recursive function
Diez B. Roggisch
deets at web.de
Wed Oct 6 18:29:09 EDT 2010
TP <Tribulations at Paralleles.invalid> writes:
> Hi,
>
> I have a function f that calls itself recursively. It has a list as second
> argument, with default argument equal to None (and not [], as indicated at:
> http://www.ferg.org/projects/python_gotchas.html#contents_item_6 )
>
> This is the outline of my function:
>
> def f ( argument, some_list = None ):
>
> if some_list == None:
> some_list = []
> [...]
> # creation of a new_argument
> # the function is called recursively only if some condition is respected
> if some_condition:
> some_list.append( elem )
> f( new_argument, some_list )
> # otherwise, we have reached a leaf of the a branch of the recursive tree
> # (said differently, terminal condition has been reached for this branch)
> print "Terminal condition"
>
> The problem is that when the terminal condition is reached, we return back
> to some other branch of the recursive tree, but some_list has the value
> obtained in the previous branch!
> So, it seems that there is only one some_list list for all the recursive
> tree.
> To get rid of this behavior, I have been compelled to do at the beginning of
> f:
>
> import copy from copy
> some_list = copy( some_list )
>
> I suppose this is not a surprise to you: I am compelled to create a new
> some_list with the same content.
> So, if I am right, all is happening as if the parameters of a function are
> always passed by address to the function. Whereas in C, they are always
> passed by copy (which gives relevance to pointers).
>
> Am I right?
Yes and no. For some sensible definition of yes (this is to avoid the
*endless* discussions about python parameter passing semantics and it's
relation to common, yet misunderstood or unprecisely defined definitions
of parameter passing), passing around a mutable object (such as a list
or dictionary) will be like a pointer - mutations are visible to all
others having a reference to it.
You are wrong though that C-semantics are different, meaning that
"passing by copy" is not what happens. Some things are copied (primitive
types, structs that are passed directly). But not, for example - and
relevant to this case - arrays (as they are "only" pointers), lists (as they
don't exist, but are modeled by structs containing pointers).
Back to your example: your solution is perfectly fine, although a bit
costly and more error-prone if you happen to forget to create a copy.
A safer alternative for these cases is using tuples, because they are
immutable.
Diez
More information about the Python-list
mailing list