使用append方法和+运算符追加到列表会在Python中产生不同的结果吗?

时间:2015-09-17 17:08:22

标签: python

当我使用mylist + [ newmember ]语法时,我的算法运行得很好。

class Node:
    def __init__( self, label, value, child1=None, child2=None ):
        self.label = label
        self.val = value
        self.children = []
        if child1 != None:
            self.children.append( child1 )
        if child2 != None:
            self.children.append( child2 )

b = Node( 'b', 3 )
c = Node( 'c', 12 )
a = Node( 'a', 5, b, c )

def check( path, item, slns ):
    node = path[ -1 ]
    if node.val == item:
        slns.append( path )
    if len( node.children ) > 0:
        for i in node.children:
            check( path + [ i ], item, slns )                       # <<<< This works!

def search( root, item ):
    slns = []
    check( [ root ], item, slns )
    return slns

resultpath = search( a, 12 )
for i in resultpath:
    for j in i:
        print( j.label )

但是在使用带有mylist.append( newmember )语法(即check( path.append( i ), item, slns)的注释行(第21行)尝试之后,我将其更改为此。我收到了这个错误。

Traceback (most recent call last):
  File "tree2.py", line 28, in <module>
    resultpath = search( a, 12 )
  File "tree2.py", line 25, in search
    check( [ root ], item, slns )
  File "tree2.py", line 21, in check
    check( path.append( i ), item, slns )
        # <<<< This works!
  File "tree2.py", line 16, in check
    node = path[ -1 ]
TypeError: 'NoneType' object is not subscriptable

我在这个网站上阅读其他答案让我相信,在追加项目而不是列表时,除了性能差异之外,附加到列表的两种方式是等效的。你能解释为什么path.append( i )path + [ i ]会在这种情况下产生不同的结果,以及为什么会出现这种错误?

2 个答案:

答案 0 :(得分:2)

区别在于lst.append(item)item附加到现有列表(就地),并在None运算符(+)时返回__add__返回连接的结果(新列表)。

因此,当您致电check( path.append(i), item, slns )时,您确实会修改列表path,但您实际上会调用check(None , item, slns )而不是新列表作为第一个参数。

答案 1 :(得分:1)

list.append()是一个就地操作,它不返回任何内容,因此该调用返回None

当你这样做时 -

check( path.append( i ), item, slns )

您实际上是将path.append()的返回值发送给check()path.append()的返回值为无,因此您发送None作为第一个参数,导致您的问题。

我会说,如果第一种方法有效,那看起来更干净。当您使用path.append()时,它最终会就地附加path对象,并且由于您没有在任何地方创建新路径list,因此它将始终更新相同的路径对象,你最终会得到错误的结果。

执行list + list1时,创建一个新列表,表达式返回该值。

另外,一个建议是,不是创建slns作为列表列表,而是应该使用slns.extend(path)创建一个简单的列表,然后将其视为一个简单的列表,示例 -

def check( path, item, slns ):
    node = path[ -1 ]
    if node.val == item:
        slns.extend( path )
    if len( node.children ) > 0:
        for i in node.children:
            check( path + [ i ], item, slns )                       # <<<< This works!

def search( root, item ):
    slns = []
    check( [ root ], item, slns )
    return slns

resultpath = search( a, 12 )
for i in resultpath:
    print( i.label )
python中的

list.extend将它作为参数接收的iterable元素(不是iterable本身)附加到列表中(同样这也是一个就地操作并且不返回任何东西)。