Dor Cohen
Dor Cohen

Reputation: 192

list passed with default parameter is considered as a tuple

I tried to call this function (only the first line matters):

def find_path(graph, start, end, path=[]):
    path = path + [start]
    if start == end:
        return path
    if not graph.has_key(start):
        return None
    for node in graph[start]:
        if node not in path:
            newpath = find_path(graph, node, end, path)
            if newpath: return newpath
    return None

like this:

find_path(self.neighbors, (4,4), (0,4))

but I always get this error:

    path = path + [start]
TypeError: can only concatenate tuple (not "list") to tuple

I know that I cannot change a tuple, but I assumed path is a list, and when I check it's type it says tuple, how come? what's your suggestion to solve it? thanks

Upvotes: 0

Views: 62

Answers (2)

Adam Smith
Adam Smith

Reputation: 54243

As confirmed in the comments, the context of this code looks like:

class SomeClass:

    ...
    def find_path(graph, start, end, path=[]):
        ...

In which case when you call it, it passes

find_path(graph=self, start=self.neighbors, end=(4,4), path=(0,4))

You need to define that method with the signature

def find_path(self, graph, start, end, path=[])

A note on mutable default arguments: be very careful when you decide to use them. It works in this case because the first thing you do is redefine path inside the scope of the method with path = path + [start], but if your first line was the otherwise-identical path.append(start), your method would be very hard to debug.

Default arguments are scoped at the same level as the function they belong to, so mutating one will change it for every future call to that function. Because of that "gotcha," a common idiom is:

def find_path(..., path=None):
    if path is None:
        path = []

or (equivalently but less-common)

path = [] if path is None else path

Upvotes: 3

user768518
user768518

Reputation: 114

You need to look into what is passed as an argument for "path". I suspect your code somehow feeds it a tuple.

>>> (4,4) + []
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    (4,4) + []
TypeError: can only concatenate tuple (not "list") to tuple
>>> [] + (4,4)
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    [] + (4,4)
TypeError: can only concatenate list (not "tuple") to list

The stacktrace you're getting corresponds to the 1st case, in which "path" is a tuple and [start] is, as expected, a list containing the tuple.

Upvotes: 0

Related Questions