博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python list的+,+=,append,extend
阅读量:6921 次
发布时间:2019-06-27

本文共 5182 字,大约阅读时间需要 17 分钟。

面试题之中的一个。

def func1(p):    p = p + [1]def func2(p):    p += [1]p1 = [1,2,3]p2 = [1,2,3]func1(p1)func2(p2)print p1print p2
结果:

我以为像这样的传參作为局部变量。由于都不会影响外部的list。所以答案应该是p1 =[1,2,3] ,p2=[1,2,3],然而

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

重新被面试官虐杀,不甘心的我查找了python 局部变量:

x = [1,2,3]def func(x):    print "local! original x = ",x    x  = [1]    print "local! now x = ",xfunc(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) =  46798728in func(), local! original x =  [1, 2, 3] id(x) =  46798728in func(), local! now x =  [1] id(x) =  46789512after 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) =  46339976in func(), local! original x =  [1, 2, 3] id(x) =  46339976in func(), local! now x =  [1, 2, 3, 1] id(x) =  46390664after 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) =  46536584in func(), local! original x =  [1, 2, 3] id(x) =  46536584in func(), local! now x =  [1, 2, 3, 1] id(x) =  46536584after 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) =  47191944in func(), local! original x =  [1, 2, 3] id(x) =  47191944in func(), local! now x =  [1, 2, 3, [1]] id(x) =  47191944after 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) =  48437128in func(), local! original x =  [1, 2, 3] id(x) =  48437128in func(), local! now x =  [1, 2, 3, 1] id(x) =  48437128after 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),这是证据

源码地址:

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) =  47781768in func(), local! original x =  [1, 2, 3] id(x) =  47781768in func(), local! now x =  [1, 2, 3, 1] id(x) =  47795720after 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 p1print 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,全局变量,嗯,不错(这算什么总结嘛)。

转载地址:http://zwecl.baihongyu.com/

你可能感兴趣的文章
Linux Foundation(笔记)
查看>>
【IScroll深入学习】解决IScroll疑难杂症
查看>>
[LeetCode] Insertion Sort List
查看>>
[大数据之Spark]——快速入门
查看>>
解决Eclipse里Maven工程报 An error occurred while filtering resources错误
查看>>
牛逼的 弹出层 layer !!!
查看>>
在javascript中使用wcf服务
查看>>
创业的感觉
查看>>
英特尔推出全新RRP物联网平台 计划为零售技术投资一亿美元
查看>>
中关村创业大街联合英特尔共建开放创新实验室
查看>>
Vega数据可视化工具——教你轻松玩转大数据可视化 | 附代码
查看>>
企业网络:安全只能靠两招
查看>>
中国CRM企业“学习”Salesforce,只是在集体自嗨?
查看>>
驱动智能制造的大数据时代
查看>>
智能家居独角兽将在传统企业中诞生
查看>>
IT仍是美国最佳就业岗位:人才稀缺令科技公司很着急
查看>>
Linux恶意软件将树莓派设备变成“矿工”
查看>>
拥抱开放式网络 通往下一代数据中心
查看>>
为了防止客户的丢失,请客服人员禁止做的四件事
查看>>
39人被骗147万 大麦网遭撞库带来的警醒
查看>>