Search code examples
pythonbacktracking

cannot understand the critical comma in this function


I have two questions regarding to a backtrack method. So I was looking at a function that can generate n parenthesis in all legal ways.

def gen_par(p, left, right, parens=[]):
    if left:
        gen_par(p + '(', left - 1, right)
    if right > left:
        gen_par(p + ')', left, right - 1)
    if not right:
        parens += p,
    return parens


print(gen_par('', 2, 2))
# >>> ['(())', '()()']

I noticed that there is a line parens += p, and the , at the end is doing something very important and I don't understand why.

if I take that , off, I will get this:

print(gen_par('', 2, 2))
# >>> ['(', '(', ')', ')', '(', ')', '(', ')']

In a addition, I don't understand why parens=[] has to be written in the parameter, and if I move it out to the body:

def gen_par(p, left, right):
    parens = []
    if left:
        gen_par(p + '(', left - 1, right)
    if right > left:
        gen_par(p + ')', left, right - 1)
    if not right:
        parens += p,
    return parens

This won't work.

So the two questions will be:

  1. What is the function of that ,
  2. Why is parens needs to be in the parameter area?

Thanks,


Solution

  • The first part of the question is already answered -- comma is what create tuples, not parentheses. For a caveat, please see a question of mine: Why do tuples need parantheses in list comprehension

    The second part of your question is pretty simple: In your second code you are treating parens as a local variable which gets reset in each iteration, and the function returns an empty list at the end. You can treat it as a global variable to get a result equivalent to the first code, like so:

    parens = []
    
    def gen_par(p, left, right):
        global parens
        if left:
            gen_par(p + '(', left - 1, right)
        if right > left:
            gen_par(p + ')', left, right - 1)
        if not right:
            parens += p,
        return parens
    
    print(gen_par('', 2, 2))
    # Returns ['(())', '()()'] correctly.