【问题标题】:Unexpected list behaviour on append in pythonpython中追加的意外列表行为
【发布时间】:2016-01-31 10:33:57
【问题描述】:

我正在 Interviewbit 上解决这个问题:

给定一组不同的整数 S,返回所有可能的子集。子集中的元素必须按非降序排列。解集不得包含重复的子集。

这是我的简单自我解释代码:

ans_list=[]

def solve(i,a,tmp,l,k):
    global ans_list
    if i==l :
      print "List to append:     " ,tmp
      ans_list.append(tmp) 
      print "ans_list currently: ", ans_list
      return

    j=k
    while j < len(a):
      tmp.append(a[j])
      solve(i+1,a,tmp,l,j+1)
      tmp.pop()
      j+=1


class Solution:
    # @param a : list of integers
    # @return a list of list of integers
    def subsets(self, a):
      a=sorted(a)
      global ans_list
      tmp=[]
      i=0
      for l in range(len(a)+1):
        solve(0,a,tmp,l,0)
      return ans_list

def main():
  a=[1,2,3]
  ob=Solution()
  li=ob.subsets(a)
  print "Ans:" ,li

if __name__ == '__main__':
    main()

这是输出:

List to append:    []
Current ans_list:  [[]]
List to append:    [1]
Current ans_list:  [[1], [1]]
List to append:    [2]
Current ans_list:  [[2], [2], [2]]
List to append:    [3]
Current ans_list:  [[3], [3], [3], [3]]
List to append:    [1, 2]
Current ans_list:  [[1, 2], [1, 2], [1, 2], [1, 2], [1, 2]]
List to append:    [1, 3]
Current ans_list:  [[1, 3], [1, 3], [1, 3], [1, 3], [1, 3], [1, 3]]
List to append:    [2, 3]
Current ans_list:  [[2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3]]
List to append:    [1, 2, 3]
Current ans_list:  [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]

Ans: [[], [], [], [], [], [], [], []]

我什至尝试将ans_list 作为参数而不是全局变量传递,但结果是一样的。甚至尝试使用字典而不是列表列表,但它会导致相同的行为。然而我注意到的一件有趣的事情是,当我在 solve 函数中将 ans_list.append(tmp) 更改为 ans_list.extend(tmp) 时,输出变为:

List to extend:    []
Current ans_list:  []
List to extend:    [1]
Current ans_list:  [1]
List to extend:    [2]
Current ans_list:  [1, 2]
List to extend:    [3]
Current ans_list:  [1, 2, 3]
List to extend:    [1, 2]
Current ans_list:  [1, 2, 3, 1, 2]
List to extend:    [1, 3]
Current ans_list:  [1, 2, 3, 1, 2, 1, 3]
List to extend:    [2, 3]
Current ans_list:  [1, 2, 3, 1, 2, 1, 3, 2, 3]
List to extend:    [1, 2, 3]
Current ans_list:  [1, 2, 3, 1, 2, 1, 3, 2, 3, 1, 2, 3]

Ans: [1, 2, 3, 1, 2, 1, 3, 2, 3, 1, 2, 3]

这几乎是意料之中的。现在我不确定在 python 中附加列表和字典的这种意外行为的原因是什么,而 extend 给出了正确的响应。任何帮助将不胜感激。

我是 python 新手并使用 Python 2.7.10

【问题讨论】:

    标签: python list dictionary recursion append


    【解决方案1】:

    问题是您在 subsets() 中的循环之外创建了 tmp。现在 solve()tmp 的每次使用都将指向同一个列表,并且每个操作都将在 ans_list 中的每个元素上执行,包括 pop()。

    有很多方法可以解决这个问题,但如果您想要最少的代码更改,只需导入 copy 模块并进行更改:

    ans_list.append(tmp) 
    

    到:

    ans_list.append(copy.deepcopy(tmp))
    

    编辑(我的解决方案):

    ans = set()
    for i in range(len(a)+1):
        for j in range(len(a)+1):
            ans.add(tuple(a[i:j]))
    

    【讨论】:

    • 感谢您的帮助。它解决了我的问题。您能否链接其他可用于解决此问题的方法的帮助。
    • 我认为您应该重新设计解决方案,而不是修复它。这个问题可以在 5-6 pythonic 行中解决。如果你愿意,我可以发布我的解决方案
    • 这是我在 python 中的第三个代码。我会尝试重新设计它,也很想看到你的,我很想知道其他可以解决问题的方法,只是为了扩展我的知识。
    • (抱歉回复晚了)我不是 python 专家,我敢肯定有一个单线可以杀死它。无论如何,我编辑了我的答案以包含我的解决方案。