首页 > 代码库 > python list的+,+=,append,extend
python list的+,+=,append,extend
面试题之中的一个。
def func1(p): p = p + [1] def func2(p): p += [1] p1 = [1,2,3] p2 = [1,2,3] func1(p1) func2(p2) print p1 print p2结果:
我以为像这样的传參作为局部变量。由于都不会影响外部的list。所以答案应该是p1 =[1,2,3] ,p2=[1,2,3],然而
>>> [1, 2, 3] [1, 2, 3, 1] >>>
x = [1,2,3] def func(x): print "local! original x = ",x x = [1] print "local! now x = ",x func(x) print "global! x = ",x结果:
local! original x = [1, 2, 3] local! now x = [1] global! x = [1, 2, 3]没错啊。我还记得要用全局变量得加global x 之类的语句呢。
为了保险起见,加一个id(),查查看对象是不是同一个先:
x = [1,2,3] print "before func(), global! x = ",x,"id(x) = ",id(x) def func(x): print "in func(), local! original x = ",x,"id(x) = ",id(x) x = [1] print "in func(), local! now x = ",x,"id(x) = ",id(x) func(x) print "after func(), global! x = ",x,"id(x) = ",id(x)结果:
before func(), global! x = [1, 2, 3] id(x) = 46798728 in func(), local! original x = [1, 2, 3] id(x) = 46798728 in func(), local! now x = [1] id(x) = 46789512 after func(), global! x = [1, 2, 3] id(x) = 46798728
恩,能够看到,全局变量中的id(x) = 46798728,x进到func()中,由于运行了x = [1],才变成id(x) = 46789512。(合情合理)
这也说明python的确是传引用入函数。(然并卵)
利用id(x),查看下x = x + [1]对象是怎么变化的吧:
x = [1,2,3] print "before func(), global! x = ",x,"id(x) = ",id(x) def func(x): print "in func(), local! original x = ",x,"id(x) = ",id(x) x = x + [1] print "in func(), local! now x = ",x,"id(x) = ",id(x) func(x) print "after func(), global! x = ",x,"id(x) = ",id(x)结果:
before func(), global! x = [1, 2, 3] id(x) = 46339976 in func(), local! original x = [1, 2, 3] id(x) = 46339976 in func(), local! now x = [1, 2, 3, 1] id(x) = 46390664 after func(), global! x = [1, 2, 3] id(x) = 46339976啊。x = x + [1],是新建了一个对象,id(x) = 46390664。
利用id(x),查看下x += [1]对象是怎么变化的吧:
x = [1,2,3] print "before func(), global! x = ",x,"id(x) = ",id(x) def func(x): print "in func(), local! original x = ",x,"id(x) = ",id(x) x += [1] print "in func(), local! now x = ",x,"id(x) = ",id(x) func(x) print "after func(), global! x = ",x,"id(x) = ",id(x)结果:
before func(), global! x = [1, 2, 3] id(x) = 46536584 in func(), local! original x = [1, 2, 3] id(x) = 46536584 in func(), local! now x = [1, 2, 3, 1] id(x) = 46536584 after func(), global! x = [1, 2, 3, 1] id(x) = 46536584啊,id(x)全程一样。x += [1],python直接就在原对象上操作,还真是够懒的说。
利用id(x),查看下x.append([1])对象时怎样变化的吧:
x = [1,2,3] print "before func(), global! x = ",x,"id(x) = ",id(x) def func(x): print "in func(), local! original x = ",x,"id(x) = ",id(x) x.append([1]) print "in func(), local! now x = ",x,"id(x) = ",id(x) func(x) print "after func(), global! x = ",x,"id(x) = ",id(x)结果:
before func(), global! x = [1, 2, 3] id(x) = 47191944 in func(), local! original x = [1, 2, 3] id(x) = 47191944 in func(), local! now x = [1, 2, 3, [1]] id(x) = 47191944 after func(), global! x = [1, 2, 3, [1]] id(x) = 47191944啊,id(x)全程一样,看来list的属性方法都是在原对象上操作的吧,我记得list.sort()也是,待会要验证的list.extend()预计也是。
利用id(x),查看下x.extend([1])对象时怎样变化的吧:
x = [1,2,3] print "before func(), global! x = ",x,"id(x) = ",id(x) def func(x): print "in func(), local! original x = ",x,"id(x) = ",id(x) x.extend([1]) print "in func(), local! now x = ",x,"id(x) = ",id(x) func(x) print "after func(), global! x = ",x,"id(x) = ",id(x)结果:
before func(), global! x = [1, 2, 3] id(x) = 48437128 in func(), local! original x = [1, 2, 3] id(x) = 48437128 in func(), local! now x = [1, 2, 3, 1] id(x) = 48437128 after func(), global! x = [1, 2, 3, 1] id(x) = 48437128果然id(x)全程一样。
话说list.append()是追加,extend()是拓展,他们的差别大概就是:
>>> a = [1,2,3] >>> b = [4,5,6] >>> c = [7,8,9] >>> a.append(b) >>> a [1, 2, 3, [4, 5, 6]] >>> c.extend(b) >>> c [7, 8, 9, 4, 5, 6] >>>看了上面的几段代码,聪明的你应该也能看出来:
list1 += list2 等价于 list1.extend(list2),这是证据:
源码地址:http://svn.python.org/view/python/trunk/Objects/listobject.c?
view=markup
913 static PyObject * 914 list_inplace_concat(PyListObject *self, PyObject *other) 915 { 916 PyObject *result; 917 918 result = listextend(self, other); //+=果然用了listextend() 919 if (result == NULL) 920 return result; 921 Py_DECREF(result); 922 Py_INCREF(self); 923 return (PyObject *)self; 924 }
利用id(x)。查看下global x下。对象的变化吧:
x = [1,2,3] print "before func(), global! x = ",x,"id(x) = ",id(x) def func(): global x print "in func(), local! original x = ",x,"id(x) = ",id(x) x = x + [1] print "in func(), local! now x = ",x,"id(x) = ",id(x) func() print "after func(), global! x = ",x,"id(x) = ",id(x)结果:
before func(), global! x = [1, 2, 3] id(x) = 47781768 in func(), local! original x = [1, 2, 3] id(x) = 47781768 in func(), local! now x = [1, 2, 3, 1] id(x) = 47795720 after func(), global! x = [1, 2, 3, 1] id(x) = 47795720啊,global就保证了,即使我的变量x在函数中指向对象变了,外部的x也会指向新的对象。
回到面试题:
def func1(p): p = p + [1] def func2(p): p += [1] p1 = [1,2,3] p2 = [1,2,3] func1(p1) func2(p2) print p1 print p2
p1传入func1()。由于+操作,生成一个新的对象。但没有return给外部的p1。所以外部的p1=[1,2,3]。
p2传入func2(),由于+=操作,就是list.extend()。操作。在原对象操作。所以p2=[1,2,3,1]。
吐槽下:
事实上python在函数中參数是传引用的,假设一个对象obj进到函数中,被改变,那不管在哪里这个obj就是被改变了。并没有什么副本什么的。
那为什么有些时候看起来。函数中obj怎么被改变,外部的obj都岿然不动,啊,由于这个被改变后的obj不是原来的它了。
比方x = x + [1]。新的x真的是原来传进来的x吗?不是的。
此时的x是新的对象了(看id就知道了)。先前传进来的x。并没有被改变。
一点浅见,求打脸。
总结:
1、list + 创建一个新的对象。
2、list的 += 和 list.extend(),等价。都是在原对象上操作。
3、list.append()。也是在原对象上操作。
4、global,全局变量,嗯,不错(这算什么总结嘛)。
python list的+,+=,append,extend