无法理解此功能中的关键逗号

时间:2019-02-07 16:16:20

标签: python backtracking

关于回溯方法,我有两个问题。因此,我正在研究一个可以通过所有合法方式生成n括号的函数。

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))
# >>> ['(())', '()()']

我注意到parens += p,行,最后的,行很重要,我不明白为什么。

如果我取消了,,我会得到的:

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

此外,我不明白为什么必须在参数中写入parens = []以及将其移到正文中的原因:

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

这行不通。

因此,两个问题将是:

  1. ,的功能是什么
  2. 为什么parens必须位于参数区域?

谢谢

2 个答案:

答案 0 :(得分:1)

与流行的看法相反,您不需要括号即可创建元组:

>>> x = 1,
>>> type(x)
<type 'tuple'>

唯一需要加括号的地方是使构成元组的逗号与逗号的另一种用法区分开。例如,逗号也用于将参数分开给函数,并且这样的参数列表中的尾部逗号是可选的,因此

>>> type(1,)   # Equivalent to type(1)
<type 'int'>

但是

>>> type((1,))  # or type((1,),)
<type 'tuple'>

对于第二个问题,请不要使用可变的默认参数。相反,请显式传递必要的列表,以使变异的默认参数不会干扰对gen_par的其他调用。

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


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

答案 1 :(得分:1)

问题的第一部分已经回答-逗号是创建元组而不是括号的原因。有关警告,请参阅我的问题:Why do tuples need parantheses in list comprehension

问题的第二部分非常简单:在第二个代码中,您将parens视为局部变量,该变量在每次迭代中都会重置,该函数最后返回一个空列表。您可以将其视为全局变量,以获得与第一个代码相同的结果,如下所示:

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.