Python中的递归类对象和成员变量

Python中的递归类对象和成员变量,python,python-2.7,object,recursion,instance,Python,Python 2.7,Object,Recursion,Instance,遵守以下代码: class permcom: def __init__(self, INPUT_SET, IS_PERM, REPETITION): self.end_set = [] self.input_set = INPUT_SET self.is_perm = IS_PERM self.repetition = REPETITION def helpfunc(self, seen, depth, current): if depth ==

遵守以下代码:

class permcom:
  def __init__(self, INPUT_SET, IS_PERM, REPETITION):
    self.end_set = []
    self.input_set = INPUT_SET
    self.is_perm = IS_PERM
    self.repetition = REPETITION
  def helpfunc(self, seen, depth, current):
    if depth == 0:
      self.end_set.append(seen)
    else:
      for i in range(0, len(self.input_set)):
        if(self.repetition):
          seen.append(self.input_set[i])
          if(self.is_perm):
            self.helpfunc(seen, depth - 1, 0)
          else:
            self.helpfunc(seen, depth - 1, i)
          del seen[-1]

# return all permutations with repetition
def rapwr(INPUT_SET, subset_size):
  instance = permcom(INPUT_SET, True, True)
  A = []
  instance.helpfunc(A, subset_size, 0)
  return instance.end_set

A = [1,2,3]
B = rapwr(A, 2)
for i in range(0, len(B)):
  print B[i]
输出如下:

[]
[]
[]
[]
[]
[]
[]
[]
[]
然而,预期输出如下:

[1, 1]
[1, 2]
[1, 3]
[2, 1]
[2, 2]
[2, 3]
[3, 1]
[3, 2]
[3, 3]

我花了太多的时间研究这段代码,不幸的是,我仍然无法准确地找出错误所在。关于Python中成员变量的工作原理,我一定有一些基本的不了解,但我仍然不太了解这里发生了什么,以及为什么代码不工作。有人能解释一下吗?

简短的回答

您需要的是列表切片
[:]
。更改声明

if depth == 0:
  self.end_set.append(seen)

给出了预期的答案

长答案

在python解释器中尝试此示例代码

a = [1,2]
b = []
b.append(a)
a[0] = 3
print b
# output is [[3, 2]]
现在试试这个代码

a = [1,2]
b = []
b.append(a[:])
a[0] = 3
print b
# output is [[1, 2]]
为什么会这样?在第一种情况下,当您将
a
附加到列表
b
时,附加的不是
a
的值,而是
[1,2]
值的引用/标记。您可以通过打印
id(b[0])
id(a)
来验证这一点两者将是相同的值。因此,当您修改
a
列表中的任何值时,
b
列表中的值也会更改

代码中的情况也是如此。由于您正在执行
del seen[-1]
,因此
self.end\u set
中的相应值也将被删除。您可以通过在
depth==0
块中打印
self.end\u set
的值来确认这一点

要避免这种情况,请将一个列表的克隆附加到另一个列表。这是通过使用拼接语法
[:]
完成的。这将创建列表从开始到结束的副本。您可以了解有关切片的更多信息

PS:使用切片时,尝试打印两个列表的
id()
,值将不同

这是我得到的

a = [1,2]
b = []
b.append(a)
print id(b[0])
#output is 43337352L
print id(a)
#output is 43337352L
b = []
b.append(a[:])
print id(b[0])
#output is 43337608L
为了更好地理解上述内容,请查看此python

更新:一些建议

  • 由于
    B
    self.input\u set
    都是列表,因此对于B中的i和self.input\u set更喜欢使用惯用的
  • 确保函数名是可以理解的。总有一天它会帮你的。通常,如果要求您为变量或函数名编写注释,最好使用注释本身的缩写版本来命名函数/变量。因此,
    rapwr
    可以重命名为
    return\u all\u permutations\u with repeation
    。虽然名称很大,但是现在不需要查看方法体就可以很容易地理解它的作用

  • 简短回答

    您需要的是列表切片
    [:]
    。更改声明

    if depth == 0:
      self.end_set.append(seen)
    

    给出了预期的答案

    长答案

    在python解释器中尝试此示例代码

    a = [1,2]
    b = []
    b.append(a)
    a[0] = 3
    print b
    # output is [[3, 2]]
    
    现在试试这个代码

    a = [1,2]
    b = []
    b.append(a[:])
    a[0] = 3
    print b
    # output is [[1, 2]]
    
    为什么会这样?在第一种情况下,当您将
    a
    附加到列表
    b
    时,附加的不是
    a
    的值,而是
    [1,2]
    值的引用/标记。您可以通过打印
    id(b[0])
    id(a)
    来验证这一点两者将是相同的值。因此,当您修改
    a
    列表中的任何值时,
    b
    列表中的值也会更改

    代码中的情况也是如此。由于您正在执行
    del seen[-1]
    ,因此
    self.end\u set
    中的相应值也将被删除。您可以通过在
    depth==0
    块中打印
    self.end\u set
    的值来确认这一点

    要避免这种情况,请将一个列表的克隆附加到另一个列表。这是通过使用拼接语法
    [:]
    完成的。这将创建列表从开始到结束的副本。您可以了解有关切片的更多信息

    PS:使用切片时,尝试打印两个列表的
    id()
    ,值将不同

    这是我得到的

    a = [1,2]
    b = []
    b.append(a)
    print id(b[0])
    #output is 43337352L
    print id(a)
    #output is 43337352L
    b = []
    b.append(a[:])
    print id(b[0])
    #output is 43337608L
    
    为了更好地理解上述内容,请查看此python

    更新:一些建议

  • 由于
    B
    self.input\u set
    都是列表,因此对于B中的i
    和self.input\u set更喜欢使用惯用的
  • 确保函数名是可以理解的。总有一天它会帮你的。通常,如果要求您为变量或函数名编写注释,最好使用注释本身的缩写版本来命名函数/变量。因此,
    rapwr
    可以重命名为
    return\u all\u permutations\u with repeation
    。虽然名称很大,但是现在不需要查看方法体就可以很容易地理解它的作用

  • 你能详细解释一下你的代码应该做什么吗?你能详细解释一下你的代码应该做什么吗?